Manipulation de chaînes de caractères |
||||
![]() Le langage C n'est certes pas un langage récent, mais il propose au programmeur au travers de la bibliothèque standard un grand nombre de routines dédiées à la manipulation de chaînes de caractères. Rappelons qu'en C une chaîne de caractères ou 'string', est un tableau de type char dont la dernière case contient le caractère nul '\0' indiquant la fin de la string. Pour utiliser les fonctions que nous allons aborder dans ce cours il est nécessaire d'inclure dans vos programmes les header files stdlib.h et string.h |
||||
Sommaire
4. strcpy
5. strncpy
7. strcat
8. strncat
10. strcmp
11. strncmp
|
||||
Les types utilisés par les fonctions de manipulation de strings | ||||
Lorsqu'on utilise les fonction de manipulation de
chaînes, on est amené a utilisé divers types que nous allons tout de suite
présenter.
|
||||
const char * |
||||
il s'agit d'un argument de type chaîne de
caractère se terminant par un '\0' qui ne sera pas modifié par la fonction.
|
||||
char * |
||||
il s'agit généralement d'une string
devant être modifié par la fonction.
|
||||
typedef unsigned long size_t |
||||
représente une valeur de type unsigned
long (type souvent utilisé pour le renvoie de valeur par les fonctions).
|
||||
strlen : Connaître la longueur d'une chaîne de caractères | ||||
La fonction strlen
|
||||
size_t strlen(const char * s); |
||||
renvoie la longueur de la chapîne qu'on lui
passe en argument.
En fait il serait très simple de programmer nous même cette méthode ainsi : |
||||
size_t PWGStrlen(const char * s) { size_t increment; char c; //incrementer 'increment' tant qu'on a //pas le caractere nul while( (c = *(s + increment)) != '\0') { increment++; } //renvoyer la taille return increment; } |
||||
Voyons un exemple
|
||||
#include <string.h> #include <stdlib.h> #include stdio.h> int main(int argc, char * argv) { //valeur qui va contenir la taille des arguments passé au programme size_t tailleArgument; //increment standard int i; //passer le nom du programme argc--; argv++; if (!argc) { fprintf(stderr, "vous devez au moins passer un argument au programme !\n"); exit(0); } while(i < argc) { //prendre la taille de l'argument tailleArgument = strlen(argv[i]); //afficher infos printf("l'argument %d a pour libellé :%s et pour taille %d\n", i, argv[i], tailleArgument); } return 0; } |
||||
Copie de chaînes de caractères | ||||
Les fonctions strcpy et strncpy
permettent de recopier une chaîne de caractère passé en paramètre vers
un espace alloué de la mémoire.
|
||||
char *strcpy(char *dest, const char *src); char *strncpy(char *dest, const char *src, size_t nb); |
||||
voyons ces fonctions plus en détails.
|
||||
|
||||
strcpy | ||||
La fonction strcpy
|
||||
char *strcpy(char *dest, const char *src); |
||||
recopie le contenu de la chaîne de caractère pointée par src vers l'adresse contenue dans dest. Elle retourne en outre la chaîne obtenue.
Un petit exemple : |
||||
#include <stdio.h> #include <string.h> #include <stdlib.h> int main( void ) { char buffer[80]; strcpy( buffer, "Hello world" ); printf( "%s\n", buffer ); return 0; } |
||||
donne la sortie :
|
||||
Hello world |
||||
strncpy | ||||
La fonction strncpy
|
||||
char *strncpy(char *dest, const char *src, size_t nb); |
||||
fonctionne sur le même principe que strcpy mais on lui passe un argument suplémentaire :nb. Elle copie en effet le nombre de caractère contenu dans nb à l'adresse de dest.
Un petit exemple : |
||||
#include <stdio.h> #include <stdlib.h> #include <string.h> int main( void ) { char buffer[15]; printf( "%s\n", strncpy( buffer, "abcdefg", 10 ) ); printf( "%s\n", strncpy( buffer, "1234567", 6 ) ); printf( "%s\n", strncpy( buffer, "abcdefg", 3 ) ); printf( "%s\n", strncpy( buffer, "*******", 0 ) ); return 0; } |
||||
produit la sortie :
|
||||
abcdefg 123456g abc456g abc456g |
||||
dans l'exemple ci-dessus nous l'affichons pas le
contenu pointé par la variable buffer mais la valeur renvoyée par
strncpy, ce qui revient au même.
|
||||
La concatenation de chaînes de caractères | ||||
Les fonctions strcat et strncat
concatènent deux chaînes de caractères ensemble.
|
||||
char *strcat(char *dest, const char *src): char *strncat(char *dest, const char *src, size_t nb): |
||||
|
||||
strcat | ||||
La fonction strcat
|
||||
char *strcat(char *dest, const char *src): |
||||
La fonction strcat ajoute la chaîne
pointée par src à la chaine pointée par dest. Le caractère nul
'\0' de fin de chaine de dest est alors remplacé par le premier caractère de
la string pointée par src.
L'initialisation de dest est souvent la cause principale d'erreur dans un programme (voir le dernier point de ce chapitre).
Il est important que la zone mémoire pointée par dest soit assez grand pour contenir la chaine src dans son ensemble. De même on déconseillera aux apprentis magicien de faire se chevaucher les chaînes dest et src : les résultats sont completement imprévisibles. Exemple : |
||||
#include <stdio.h> #include <string.h> #include <stdlib.h> int main( void ) { //bugger d'une taille supérieure a ce qu'on veut y placer char buffer[80]; // copier hello dans la chaine (qui est vide pour l'instant) strcpy( buffer, "Hello " ); //concatener la chaine world strcat( buffer, "world" ); //afficher le resultat printf( "%s\n", buffer ); return 0; } |
||||
donne la sortie
|
||||
Hello world |
||||
De même en second exemple nous pourrions
créer une fonction qui ajoute une extension à un nom de fichier
|
||||
#include <stdio.h> #include <string.h> #include <stdlib.h> /** * fonction qui accepte une chaine en entrée * qui ajoute à cette chaine la string ".cpp" et qui la * renvoie */ char* extensionCPP(char *nomFichier) { //buffer qui va contenir la chaine en entier char buffer; //allouer un espace mémoire suffisant pour accepter la chaine //+ l'extension .cpp buffer = (char *)malloc(strlen(nomFichier)+4+1); //copier le nom de fichier strcpy(buffer, nomFichier); //ajouter l'extension strcat(buffer, ".cpp"); //renvoyer la nouvelle chaine return buffer; } |
||||
La valeur "4+1" dans la ligne :
|
||||
buffer = (char *)malloc(strlen(nomFichier)+4+1); |
||||
le nombre 4 représentant le nomber
de caractère dans l'extension ".cpp" et le 1 est ajouté pour
permettre l'ajout du caractère final nul '\0' à la fin de la chaine.
Nous pouvons facilement reprogrammer la fonction strcat par l'intermédiaire de la fonction strcpy : |
||||
#include <stdio.h> #include <string.h> #include <stdlib.h> /** * notre strcat a nous */ char* PWGStrcat(char *dest, const char * src) { //buffer qui va contenir la chaine en entier char buffer; //faire pointer buffer sur dest buffer = dest //se placer à la fin de la chaine buffer = buffer + strlen(dest); //maintenant qu'on est à la fin //copier la chaine src strcpy(buffer, src); //renvoyer la nouvelle chaine return buffer; } |
||||
Comme on le voit il s'agit d'une fonction
relativement simple.
|
||||
strncat | ||||
La fonction strncat
|
||||
char *strncat(char *dest, const char *src, size_t n): |
||||
fonctionne sur le même principe que
strcat mais accepte un argument de plus : nb. La valeur entière contenue
dans nb indique les nb premier caractères de src à ajouter
à dest.
Il est important que la zone mémoire pointée par dest soit assez grand pour contenir la chaine src dans son ensemble. De même on déconseillera aux apprentis magicien de faire se chevaucher les chaînes dest et src : les résultats sont completement imprévisibles. Exemple : |
||||
#include <stdio.h> #include <stdlib.h> #include <string.h> char buffer[80]; int main( void ) { strcpy( buffer, "Hello " ); strncat( buffer, "world", 8 ); printf( "%s\n", buffer ); strncat( buffer, "*************", 4 ); printf( "%s\n", buffer ); return 0; } |
||||
produit la sortie
|
||||
Hello world Hello world**** |
||||
La comparaison de chaînes de caractères | ||||
La comparaison de chaînes de
caractères s'effectue au travers de deux fonctions :
|
||||
int strcmp(const char *s1, const char *s2); inr strncmp(const char *s1, const char *s2, size_t nb); |
||||
La compariaon s'effectue entre deux chaînes
de caractères (s1 et s2) suivant le système lexicogaraphique (celui
de tout doictionnaire).
Les deux fonctions retournent une valeur négative si s1 est avant s2, positive si s1 est après s2 et égale à 0 si s1 est égale à s2. |
||||
|
||||
strcmp | ||||
La fonction strcmp
|
||||
int strcmp(const char *s1, const char *s2); |
||||
compare les deux chaînes de
caractères s1 et s2 qu'on lui passe en argument.
Exemple : |
||||
#include <stdio.h> #include <string.h> #include <stdlib.h> int main( void ) { printf( "%d\n", strcmp( "abcdef", "abcdef" ) ); printf( "%d\n", strcmp( "abcdef", "abc" ) ); printf( "%d\n", strcmp( "abc", "abcdef" ) ); printf( "%d\n", strcmp( "abcdef", "mnopqr" ) ); printf( "%d\n", strcmp( "mnopqr", "abcdef" ) ); printf( "%d\n", strcmp( "chien", "chiens" ) ); printf( "%d\n", strcmp( "chien", "Chiens" ) ); return 0; } |
||||
donne la sortie :
|
||||
0 1 -1 -1 1 -1 1 |
||||
strncmp | ||||
La fonction strncmp
|
||||
inr strncmp(const char *s1, const char *s2, size_t nb); |
||||
compare les deux chaînes de
caractères s1 et s2 qu'on lui passe en argument. Elle fonctionne sur le
même principe que la fonction strcmp en comparant les nb premiers caractères de
chaque chaîne.
Exemple : |
||||
#include <stdio.h> #include <string.h> #include <stdlib.h> int main( void ) { printf( "%d\n", strncmp( "abcdef", "abcDEF", 10 ) ); printf( "%d\n", strncmp( "abcdef", "abcDEF", 6 ) ); printf( "%d\n", strncmp( "abcdef", "abcDEF", 3 ) ); printf( "%d\n", strncmp( "abcdef", "abcDEF", 0 ) ); return 0; } |
||||
affiche :
|
||||
1 1 0 0 |
||||
strchr et strrchr : Recherche d'un caractère | ||||
Les fonctions strchr et strrchr
|
||||
char *strchr(const char *s, int c); char *strrchr(const char *s, int c); |
||||
recherchent si un caractère est
présent dans une chaîne de caracteres.
La fonction strchr recherche le caractère c qu'on lui transmet en paramètre est présent dans la châine s donnée en argument. Si c'est le cas, elle retourne alors un pointeur sur la première occurence de ce caractère dans la chaîne.
Il est à noter qu'on peut donner la valeur du caractère nul '\0' à c. Dans ce cas strchr retourne un pointeur sur le dernier caractère de la chaine. La fonction strlen pourrait être programmée ainsi |
||||
#define strlen(n) strchr(n, '\0')-n |
||||
C'est à dire chercher la fin de la string
puis soustraire cette adresse finale à l'adresse de début pour obtenir par
différence la taille de la chaîne.
La fonction strrchr est identique à la fonction strchr mais elle renvoie un pointeur sur la dernière occurence du caractère c de la chaîne s. Exemple : |
||||
#include <stdio.h> #include <string.h> #include <stdlib.h> int main( void ) { char chaine[50] = "bonjour a tous et a toutes"; char *p; char *p2; p = strchr( 't', chaine); p2 = strrchr( 't', chaine); printf( "%s\n", p ); printf( "%s\n", p2 ); return 0; } |
||||
donne la sortie :
|
||||
tous et à toutes toutes |
||||
L'exemple suivant :
|
||||
#include <stdio.h> #include <string.h> #include <stdlib.h> int main( void ) { char chaine[50] = "bonjour a tous et a toutes"; char *p; char *p2; char *p3; p = strchr( 't', chaine); p2 = strrchr( 't', p); p3 = strrchr( 't', p2); printf( "%s\n", p ); printf( "%s\n", p2 ); printf( "%s\n", p3 ); return 0; } |
||||
donnerait la sortie :
|
||||
tous et a toutes t a toutes toutes |
||||
Ce dernier exemple aurait pu être
simplifié ainsi :
|
||||
#include <stdio.h> #include <string.h> #include <stdlib.h> int main( void ) { char chaine[50] = "bonjour a tous et a toutes"; char *p; char *p2; //p2 pointe sur le premier caractère de la chaîne p2 = chaine; //tant qu'il y'a une occurence du caractère... while ( (p = strchr( 't', p2)) != NULL) { printf( "%s\n", p ); //sauvegarder le bout de string restant p2 = p; } return 0; } |
||||
|
||||
strspn, strcspn, strpbrk : recherche par rapport à plusieurs caractères | ||||
Les fonctions strspn, strcspn,
strpbrk
|
||||
size_t strspn(const char *suite, const char *chaine); size_t strcspn(const char *suite, const char *chaine); char * strpbrk(const char *suite, const char *chaine); |
||||
recherchent les caractères contenu dans la
string suite à l'intérieur de la string chaine.
La fonction strspn recherche la chaîne suite à l'intérieur de la chaîne chaine. Elle renvoie le nombre le plus grand de caractères trouvés se suivant qui correspondent à suite. Par exemple, l'instruction : |
||||
strspn("jouer", "bonjour"); |
||||
renverra la valeur 2 car deux lettres se suivent
et correspondent dans les deux strings : "jo".
Autre exemple : |
||||
#include <stdio.h> #include <stdlib.h> #include <string.h> int main( void ) { printf( "%d\n", strspn( "out to lunch", "aeiou" ) ); printf( "%d\n", strspn( "out to lunch", "xyz" ) ); return 0; } |
||||
produit la sortie :
|
||||
2 0 |
||||
car deux lettres de "aeiou" ont
été trouvées dans "out to lunch" : "ou".
La seconde instruction renvoie 0 car aucune suite de lettre correspondante n'a été trouvée. La fonction strcspn renvoie la longueur du du préfixe le plus long n'appartenant pas à la string suite. L'exemple précédent avec cette fonction : |
||||
strcspn("jouer", "bonjour"); |
||||
renverrait la valeur 3. Car trois lettres se
suivent et ne correspondent pas à la chaîne suite : "bon".
Autre exemple : |
||||
#include <stdio.h> #include <string.h> #include <stdlib.h> int main( void ) { printf( "%d\n", strcspn( "abcbcadef", "cba" ) ); printf( "%d\n", strcspn( "xxxbcadef", "cba" ) ); printf( "%d\n", strcspn( "123456789", "cba" ) ); return 0; } |
||||
produit la sortie :
|
||||
0 3 9 |
||||
Enfin, la fonction strpbrk est identique à la fonction strcspn mais elle renvoie un pointeur sur le premier caractère de la chaîne suite qui appartient aussi à la chaîne chaine. Par exemple : |
||||
printf("%s\n", strpbrk("abcdefghijklm", "neon")); |
||||
va renvoyer
|
||||
efghijklm |
||||
car le premier caractère de la
chaîne "neon" se trouvant aussi dans la chaîne
"abcdefghiklm" est le caractères 'e'.
Autre exemple : |
||||
#include <stdio.h> #include <stdlib.h> #include <string.h> /** * ce programme va chercher les voyelles * dans la phrases anglaise * "Find all vowels" */ int main( void ) { char* p = "Find all vowels"; while( p != NULL ) { printf( "%s\n", p ); p = strpbrk( p+1, "aeiouAEIOU" ); } return 0; } |
||||
donne la sortie :
|
||||
Find all vowels ind all vowels all vowels owels els |
||||
strtok : Découper une chaîne de caractères en lexèmes | ||||
La fonction strtok
|
||||
char * strtok(char *source, const char *s); |
||||
permet de découper une chaîne en
token ou élements, c'est à dire en sous-mots séparés par des
caractères spéicfiés par le programmeur.
Les caractères de la chaine s sont considérés comme des séparateurs. Pour bien comprendre le fonctionnement de strtok, il faut comprendre étape par étape ce qu'elle fait. Au premier appel de strtok, les caractères de source se trouvant dans la chaîne de spéarateurs s sont ignorés (il s'agit là de séparateurs et non de lexèmes). Si tous les caractères de source sont des séparateurs, alors strtok renvoie un poniteur NULL. Si plusieurs caractères de source se suivent et n'appartiennent pas à s alors cette suite de caractères est considérée comme un lexem. La fonction strtok lis alors ce lexem jusqu'à rencontrer un séparateur ou bien la fin de la chaîne. Dans ces deux cas le séparateur dans source est replacé par le le caractères de fin de string '\0 et '\0' est aussi ajouté à la fin du lexème. Ce dernier est alors renvoyé par la fonction. Les appels suivants de la fonction strtok de la forme |
||||
strtok(NULL, s); |
||||
continuerons la rehcerche là ou elle
s'était arrétée dans la chaîne source au
précédent appel à strtok.
Exemple : |
||||
#include <stdio.h> #include <stdlib.h> #include <string.h> /** * programme qui va découper notre chaîne * en lexèmes */ int main( void ) { char* p; char* buffer; char* separateurs = { " .,!" }; buffer = strdup( Trouve les mots... Tous les mots!" ); //afficher la chaîne entière printf( "%s\n", buffer ); //premier appel, renvoie le premier mot p = strtok( buffer, separateurs ); //pour tous les mots suivants : while( p != NULL ) { //afficher le lexème printf( "lexeme : %s\n", p ); //chercher le mot suivant p = strtok( NULL, separateurs ); } printf( "%s\n", buffer ); return 0; } |
||||
produit la sortie :
|
||||
Trouve les mots... Tous les mots! lexeme:Trouve lexeme:les lexeme:mots lexeme:Tous lexeme:les lexeme:mots Trouve |
||||
par Valentin BILLOTTE vbillotte@programmationworld.com http://www.programmationworld.com Dernière mise à jour: |