Une chaine de caractères est un tableau de caractères particulier puisqu’en plus d’intégrer le code ASCII de chaque caractère, le tableau se termine par la valeur 0. Ainsi un tableau de 10 caractères initialisé avec la chaine de caractère "ABC" aura 4 cases initialisées : les 3 cases ayant les codes 65('A'),66('B') et 67('C') et la quatrième case avec la valeur 0 (fin de la chaine). Par défaut la valeur 0 est codé sur 32 bits (c’est un int) alors que '\0' est codé sur 8 bits, c’est donc cette dernière que l’on utilisera pour tester la fin de la chaine de caractères.
Comme tout tableau, il est possible de créer une chaine de caractères non initialisée.
Il existe 2 solutions permettant d'initialiser une chaine de caractères : avec les " " ou bien caractère par caractère.
Solution 1 : création d'une chaine de caractères et initialisation en utilisant " "
Solution 2 : création d'une chaine de caractères et initialisation caractères par caractères
Comme tout tableau, il est possible de modifier une case du tableau. Dans l’exemple ci-dessous, on place 'B' dans la case 0.
Quizz
3. Lire et afficher une chaine de caractères
Il est possible de lire une chaine de caractères notée mot avec la fonction gets(mot) ou scanf("%s", mot). Pour afficher sur l’écran une chaine de caractère, on utilisera les fonction puts(mot) ou printf("%s\n", mot). La fonction puts (put string) en plus d'afficher la chaine de caractères fait un saut de ligne.
Nous avons vu jusqu’ici la lecture d’une variable entière (%d), réelle (%lf) et de type caractère (%c). Il existe un dernier type de lecture : la lecture de chaine de caractères%s.
Lecture d'une chaine de caractères saisie par l'utilisateur
Affichage à l'écran d'une chaine de caractères
Quizz
A la différence avec la lecture caractère par caractère de la fonction getchar(), la lecture du buffer de caractère se fait en une seule fois avec la fonction gets. Tous les caractères saisis se trouvent dans le tableau passé en argument et le code ASCII de la touche « Entrée (ou retour charriot) » est remplacée par la valeur '\0'. Il ne reste donc plus qu’à utiliser une boucle pour lire les caractères du tableau jusqu’à trouver le '\0' terminal.
Afin de mieux comprendre comment travailler avec une chaine de caractères, prenons un exemple utilisant les fonction gets, puts, printf et la lecture des caractères de la chaine de caractères au travers une boucle for.
Exemple de code utilisant les chaines de caractères
Résultat
char chaine[80] = "Bonjour";
puts(chaine);
chaine[0] = 'b';
puts(chaine);
printf("entrer une phrase :");
gets(chaine);
printf("chaine=%s\n", chaine);
for (int i = 0; chaine[i] != '\0'; i++)
printf("chaine[%d]=%c\n",i, chaine[i]);
Bonjour
bonjour
entrer une phrase :roger
chaine=roger
chaine[0]=r
chaine[1]=o
chaine[2]=g
chaine[3]=e
chaine[4]=r
Les fonctions d'affichage printf %s ou puts utilisent le '\0' terminal pour stopper l'affichage de la chaine de caractère. Dans le programme ci-dessous, le fait de modifier la position du '\0' terminal coupe l'affichage de la chaine "bonjour" qui a été au préalable modifié en "abnjour" par la boucle for.
Programme de test des fonctions strlen, strcmp et strcpy
résultat
#include<stdio.h>
#include<string.h>
int main(){
charszSrc[80] = "Bonjour";
charszDest[80] = "Bonjour a tous";
printf("longueur de szSrc : %d\n", strlen(szSrc));
printf("longueur de szDest : %d\n", strlen(szDest));
if (strcmp(szSrc, szDest) == 0)
printf("chaines identiques\n");
else
printf("chaines differentes\n");
strcpy(szDest, szSrc);
printf("apres copie de szSrc vers szDest\n");
printf("longueur de szSrc : %d\n", strlen(szSrc));
printf("longueur de szDest : %d\n", strlen(szDest));
if (strcmp(szSrc, szDest) == 0)
printf("chaines identiques\n");
else
printf("chaines différentes\n");
return 0;
}
longueur de szSrc : 7
longueur de szDest : 14
chaines differentes
apres copie de szSrc vers szDest
longueur de szSrc : 7
longueur de szDest : 7
chaines identiques
Quizz
5. Comparaison entre gets et getchar
La lecture d'une chaine de caractère peut être faite de 2 façons :
en utilisant la fonction gets et en travaillant avec les chaines de caractères, il est alors possible de lire la chaine jusqu'au caractère '\0'
en utilisant la fonction getchar (ou scanf %c) et au travers d'une lecture caractère par caractère jusqu'au caractère '\n'
Dans l'exemple ci-dessous, nous utilisons la boucle en do while pour parcourir la chaine de caractères, mais en général on utilisera la boucle répétitive for plus compacte.
travail avec gets lecture de la chaine de caractère
Travail avec la fonction scanf %c ou getchar (lecture caractère par caractère)
#define_CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
char buffer[30],c;
int cpt = 0,i=0;
printf("entrer des caracteres:");
gets(buffer);
do {
c = buffer[i];
if (c == 'a' || c == 'A')
cpt++;
i++;
} while (c != '\0');
printf("nombre de lettre A ou a : %d\n", cpt);
return 0;
}
#define_CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
char c;
int cpt = 0;
printf("entrer des caracteres:");
do {
scanf("%c", &c);
if (c == 'a' || c == 'A')
cpt++;
} while (c != '\n');
printf("nombre de lettre A ou a : %d\n", cpt);
return 0;
}
6. Ecrire des fonctions de gestion de caractères
Nous avons vu que la différence entre une chaine de caractères et un tableau d’entier ou de réels est liée au '\0' terminal que l’on trouve en fin de chaine de caractères et qui permet de connaitre la taille de la chaine. Ainsi les fonctions associées aux chaines de caractères n’ont pas besoin de 2 arguments (le tableau et la taille du tableau) mais seulement de la chaine de caractères.
Voici 3 codes de fonctions :
strLen (qui implémente le code de la fonction strlen définie dans string.h) qui compte le nombre de caractères jusqu'au '\0' terminal
strCmp (qui implémente le code de la fonction strcmp définie dans string.h) qui compare 2 chaines de caractères et renvoie 0 si les 2 chaines sont identiques
strChr (qui implémente le code de la fonction strchr définie dans string.h) qui cherche le caractère passé en argument et compte le nombre d'occurrence
Pour ces 3 fonctions, on passe la chaine de caractères et la fonction va lire la chaine caractère par caractère jusqu'au '\0' terminal.
Code des fonctions
Appel de ces fonctions
résultat
intstrLen(charchaine[]) {
int i;
for (i = 0; chaine[i] != '\0'; i++);
return i;
}
int main(){
char mot[80] = "Boom";
printf("%s:%d\n", mot,strLen(mot));
printf("%s:%d", "bon", strLen("bon"));
}
Boom:4
bon:3
intstrCmp(charchaine1[], charchaine2[]) {
inti,cpt=0;
int n1 = strLen(chaine1);
int n2 = strLen(chaine2);
if (n1 != n2)
return (n1-n2);
for (int i = 0; i < n1; i++)
cpt += chaine1[i] - chaine2[i];
return cpt;
}
int main(){
char mot[80] = "Boom";
printf("%d\n",strCmp(mot,"BOOm"));
printf("%d", strCmp("Bon", "Bon"));
}
64
0
intstrChr(charchaine[], charc) {
int cpt = 0;
for (int i = 0; chaine[i] != '\0'; i++)
if (chaine[i] == c)
cpt++;
return cpt;
}
char mot[80] = "Boom";
printf(" %d %c dans %s\n", strChr(mot, 'o'), 'o', mot );
printf(" %d %c dans %s", strChr("bonjour", 'o'),'o', "bonjour");
2 o dans Boom
2 o dans bonjour
7. problème de sécurité gets
La fonction gets en C est notoirement dangereuse car elle ne vérifie pas la taille de la chaîne dans laquelle elle lit, ce qui peut conduire à des dépassements de tampon et des failles de sécurité. En raison de ces problèmes, elle a été retirée de la norme C11 (version 2011 du langage C)
Sous Visual Studio, on peut continuer d'utiliser gets (même si c'est déconseillé) à condition d'ajouter la macro _CRT_SECURE_NO_WARNINGS
Programme avec gets (Visual Studio)
Résultat
#define_CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdint.h>
#include<stdlib.h>
int main() {
system("CHCP 1252 > nul");
int8_t chaine[30];
printf("entrer une chaine de caractère:");
gets(chaine);
printf("n=%d\n", strlen(chaine));
}
entrer une chaine de caractère:Bonjour
n=7
Il est fortement recommandé d'utiliser fgets à la place de gets car elle permet de spécifier la taille maximale du tampon et donc de prévenir les dépassements de tampon.
Programme avec fgets (tout type de compilateur Windows Linux)