Guide complet : strcpy en C
La fonction strcpy
en C est utilisée pour copier une chaîne de caractères d’une source vers une destination. Ce guide explique son fonctionnement, ses utilisations, ses limites, et propose des exemples pratiques.
1. Introduction à strcpy
Prototype
char *strcpy(char *destination, const char *source);
Description
- But : Copier une chaîne de caractères (source) dans une autre (destination), y compris le caractère nul (
\0
) de fin. - Arguments :
destination
: Pointeur vers le tableau où la chaîne sera copiée.source
: Pointeur vers la chaîne à copier.- Retourne : Un pointeur vers la chaîne
destination
.
2. Fonctionnement
Étapes de copie
- Parcourt chaque caractère de
source
. - Copie chaque caractère dans
destination
. - Ajoute un caractère nul (
\0
) à la fin.
Conditions
- La mémoire allouée pour
destination
doit être suffisamment grande pour contenir : - Tous les caractères de
source
. - Le caractère nul de fin.
Exemple simple
#include <stdio.h>
#include <string.h>
int main() {
char source[] = "Bonjour";
char destination[20]; // Assez d'espace pour la chaîne
strcpy(destination, source);
printf("Source : %s\n", source);
printf("Destination : %s\n", destination);
return 0;
}
Sortie :
Source : Bonjour
Destination : Bonjour
3. Cas particuliers
a. Si la destination n’a pas assez d’espace
Si l’espace alloué pour destination
est insuffisant, cela peut provoquer un dépassement de mémoire (buffer overflow), entraînant des comportements imprévisibles.
Exemple problématique :
char source[] = "Très long texte";
char destination[5]; // Pas assez d'espace
strcpy(destination, source); // Comportement indéfini !
Solution : Assurez-vous que destination
dispose d’assez d’espace :
char destination[50]; // Taille appropriée
b. Si la source est vide
Si source
est une chaîne vide (""
), destination
contiendra uniquement le caractère nul (\0
).
Exemple :
char source[] = "";
char destination[10];
strcpy(destination, source);
printf("Source : '%s'\n", source);
printf("Destination : '%s'\n", destination); // Destination est vide
Sortie :
Source : ''
Destination : ''
c. Copie sur elle-même
Si source
et destination
pointent vers le même emplacement, strcpy
fonctionnera correctement. Cependant, évitez cette situation dans la pratique.
4. Limites de strcpy
a. Pas de vérification de taille
- Problème :
strcpy
ne vérifie pas sidestination
peut contenirsource
, ce qui peut causer des dépassements de mémoire. - Solution : Utilisez des alternatives sécurisées comme
strncpy
ou assurez-vous quedestination
est suffisamment grand.
Exemple avec strncpy
:
#include <string.h>
char destination[10];
strncpy(destination, source, sizeof(destination) - 1);
destination[sizeof(destination) - 1] = '\0'; // Assurez-vous que la chaîne est terminée par '\0'
b. Risque de buffer overflow
Un dépassement de mémoire peut entraîner un écrasement de données, des plantages, ou des failles de sécurité.
5. Alternatives à strcpy
a. strncpy
- Copie au maximum un nombre spécifié de caractères.
- Syntaxe :
char *strncpy(char *destination, const char *source, size_t n);
- Avantage : Permet de limiter la taille copiée.
b. strlcpy
(dans certains environnements)
- Copie une chaîne en respectant la taille maximale de
destination
. - Syntaxe :
size_t strlcpy(char *destination, const char *source, size_t size);
c. Utilisation de snprintf
pour une sécurité accrue
- Formatage sécurisé et limitation de taille.
- Syntaxe :
snprintf(destination, sizeof(destination), "%s", source);
6. Exercices corrigés
Exercice 1 : Copie d’une chaîne
Allouez deux tableaux statiques et copiez une chaîne dans le second.
Solution :
#include <stdio.h>
#include <string.h>
int main() {
char source[] = "Copie réussie";
char destination[20];
strcpy(destination, source);
printf("Source : %s\n", source);
printf("Destination : %s\n", destination);
return 0;
}
Exercice 2 : Gestion des tailles de chaînes
Copiez une chaîne seulement si l’espace alloué est suffisant.
Solution :
#include <stdio.h>
#include <string.h>
int main() {
char source[] = "Texte";
char destination[5]; // Destination trop petite
if (strlen(source) < sizeof(destination)) {
strcpy(destination, source);
printf("Copie réussie : %s\n", destination);
} else {
printf("Erreur : Espace insuffisant.\n");
}
return 0;
}
Exercice 3 : Copier une partie de la chaîne
Copiez seulement les 4 premiers caractères d’une chaîne.
Solution :
#include <stdio.h>
#include <string.h>
int main() {
char source[] = "Exemple de chaîne";
char destination[5];
strncpy(destination, source, 4);
destination[4] = '\0'; // Ajouter le caractère nul manuellement
printf("Destination : %s\n", destination);
return 0;
}
7. Bonnes pratiques
Vérifiez la taille de destination
:
- Avant de copier une chaîne, assurez-vous que
destination
est suffisamment grand.
Préférez strncpy
ou snprintf
:
- Utilisez ces alternatives si la sécurité est critique.
Évitez les dépassements de mémoire :
- En cas de doute, calculez la taille nécessaire avant l’allocation.
FAQ
Q : Quelle est la différence entre strcpy
et strncpy
?
strcpy
: Copie la chaîne entière, y compris\0
, mais sans vérifier la taille.strncpy
: Copie un nombre maximum de caractères, mais n’ajoute pas toujours le caractère nul si la source dépasse la limite.
Q : Que se passe-t-il si source
ou destination
est NULL
?
- Si
source
oudestination
estNULL
, le comportement est indéfini et le programme peut planter.
Suite du Guide : Utilisations avancées de strcpy
Utilisations avancées de strcpy
a. Manipulation de plusieurs chaînes
strcpy
peut être utilisé pour gérer plusieurs chaînes dans un programme, comme dans une liste ou une table de chaînes.
Exemple : Table de chaînes
#include <stdio.h>
#include <string.h>
int main() {
char *strings[3];
char buffer[50];
// Allocation et copie de plusieurs chaînes
for (int i = 0; i < 3; i++) {
printf("Entrez une chaîne : ");
fgets(buffer, sizeof(buffer), stdin); // Lecture de la chaîne
buffer[strcspn(buffer, "\n")] = '\0'; // Retirer le caractère de fin de ligne
strings[i] = (char *)malloc(strlen(buffer) + 1); // Allocation dynamique
if (strings[i] == NULL) {
printf("Erreur d'allocation mémoire.\n");
return 1;
}
strcpy(strings[i], buffer); // Copie dans la table
}
// Affichage des chaînes
printf("\nChaînes enregistrées :\n");
for (int i = 0; i < 3; i++) {
printf("Chaîne %d : %s\n", i + 1, strings[i]);
free(strings[i]); // Libération de la mémoire
}
return 0;
}
b. Concatenation de chaînes avec strcpy
et strcat
strcpy
est souvent utilisé avec strcat
pour créer une nouvelle chaîne à partir de plusieurs chaînes.
Exemple : Concaténation de trois chaînes
#include <stdio.h>
#include <string.h>
int main() {
char part1[] = "Bonjour, ";
char part2[] = "comment ";
char part3[] = "ça va ?";
char result[50];
// Copier et concaténer les chaînes
strcpy(result, part1);
strcat(result, part2);
strcat(result, part3);
printf("Résultat : %s\n", result);
return 0;
}
c. Copie conditionnelle
Vous pouvez conditionnellement copier une chaîne si elle répond à certains critères, comme une longueur spécifique ou un contenu particulier.
Exemple : Copie conditionnelle
#include <stdio.h>
#include <string.h>
int main() {
char source[] = "Programmation en C";
char destination[20];
// Condition : copier uniquement si la longueur est inférieure à 20
if (strlen(source) < sizeof(destination)) {
strcpy(destination, source);
printf("Copie réussie : %s\n", destination);
} else {
printf("La chaîne source est trop longue pour être copiée.\n");
}
return 0;
}
d. Utilisation avec des structures
Dans des programmes complexes, strcpy
est souvent utilisé pour copier des chaînes dans les champs d’une structure.
Exemple : Gestion des noms dans une structure
#include <stdio.h>
#include <string.h>
typedef struct {
char name[50];
int age;
} Person;
int main() {
Person p1;
// Copier des données dans la structure
strcpy(p1.name, "Alice");
p1.age = 25;
printf("Nom : %s, Âge : %d\n", p1.name, p1.age);
return 0;
}
Problèmes courants et solutions
a. Dépassement de mémoire (Buffer Overflow)
Si la chaîne source dépasse la taille allouée pour destination
, cela peut écraser d’autres données en mémoire.
Solution : Utilisez strncpy
#include <stdio.h>
#include <string.h>
int main() {
char source[] = "Chaîne très longue";
char destination[10];
// Utilisation de strncpy pour limiter la copie
strncpy(destination, source, sizeof(destination) - 1);
destination[sizeof(destination) - 1] = '\0'; // Terminaison sécurisée
printf("Destination : %s\n", destination);
return 0;
}
b. Oublier d’allouer ou de libérer de la mémoire
Lorsque vous utilisez strcpy
avec des allocations dynamiques, vous devez vous assurer que la mémoire est correctement allouée et libérée.
Exemple : Allocation et libération correcte
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char source[] = "Dynamique";
char *destination;
// Allocation dynamique
destination = (char *)malloc(strlen(source) + 1);
if (destination == NULL) {
printf("Erreur d'allocation mémoire.\n");
return 1;
}
// Copie de la chaîne
strcpy(destination, source);
printf("Destination : %s\n", destination);
// Libération de la mémoire
free(destination);
return 0;
}
c. Nullité des pointeurs
Si l’un des arguments de strcpy
est NULL
, le programme risque de planter.
Solution : Vérifiez les pointeurs
#include <stdio.h>
#include <string.h>
int main() {
char *source = NULL;
char destination[20];
if (source == NULL) {
printf("La chaîne source est NULL. Impossible de copier.\n");
} else {
strcpy(destination, source);
printf("Destination : %s\n", destination);
}
return 0;
}
Scénarios réels d’utilisation
a. Lecture d’entrée utilisateur
Copier des données saisies par l’utilisateur dans une structure ou un tableau.
Exemple :
#include <stdio.h>
#include <string.h>
int main() {
char input[50];
char processed[50];
printf("Entrez une chaîne : ");
fgets(input, sizeof(input), stdin);
input[strcspn(input, "\n")] = '\0'; // Suppression du caractère de fin de ligne
strcpy(processed, input);
printf("Vous avez saisi : %s\n", processed);
return 0;
}
b. Préparation de chemins de fichiers
Assembler un chemin de fichier à partir de plusieurs chaînes.
Exemple :
#include <stdio.h>
#include <string.h>
int main() {
char directory[] = "/home/user/";
char filename[] = "document.txt";
char filepath[100];
strcpy(filepath, directory);
strcat(filepath, filename);
printf("Chemin du fichier : %s\n", filepath);
return 0;
}
Bonnes pratiques avec strcpy
- Toujours vérifier la taille de
destination
:- Assurez-vous que
destination
peut contenirsource
et le caractère nul (\0
).
- Assurez-vous que
- Préférez
strncpy
ousnprintf
dans des scénarios critiques :- Ces fonctions limitent la taille de la chaîne copiée.
- Initialisez les pointeurs avant utilisation :
- Évitez d’utiliser des pointeurs non initialisés pour
source
oudestination
.
- Évitez d’utiliser des pointeurs non initialisés pour
- Libérez la mémoire allouée dynamiquement :
- Lorsqu’un pointeur est utilisé avec
strcpy
, n’oubliez pas de libérer la mémoire après utilisation.
- Lorsqu’un pointeur est utilisé avec