Le type char
Dans ce chapitre, nous allons porter une attention particulière au type char.
Si vous vous souvenez bien, le type char permet de stocker des nombres compris entre -128 et 127.
Si ce type char permet de stocker des nombres, il faut savoir qu'en C on l'utilise rarement pour ça. En général, même si le nombre est petit, on le stocke dans un long ou un int. Certes, ça prend un peu plus de place en mémoire, mais aujourd'hui la mémoire c'est vraiment pas ce qui manque sur un ordinateur
Vous ne tuerez pas votre ordi parce que vous utilisez des int ou des long
Le type char est en fait prévu pour stocker... une lettre !
Attention, j'ai bien dit : UNE lettre.
Comme la mémoire ne peut stocker que des nombres, on a inventé une table qui fait la conversion entre les nombres et les lettres. Cette table indique ainsi par exemple que le nombre 65 équivaut à la lettre A.
Le langage C permet de faire très facilement la traduction : lettre => nombre correspondant. Pour obtenir le nombre associé à une lettre, il suffit de mettre cette lettre entre apostrophes, comme ceci : 'A'. A la compilation, 'A' sera remplacé par la valeur correspondante.
Testons :
Code : C1
2
3
4
5
6
7
8int main(int argc, char *argv[])
{
char lettre = 'A';
printf("%d\n", lettre);
return 0;
}
Code : Console
65
On sait donc que la lettre A majuscule est représentée par le nombre 65. B vaut 66, C vaut 67 etc.
Testez avec des minuscules, et vous verrez que les valeurs sont différentes. En effet, la lettre 'a' n'est pas identique à la lettre 'A', l'ordinateur faisant la différence entre les majuscules et les minuscules.
La plupart des caractères "de base" sont codés entre les nombres 0 et 127.
Afficher un caractère
La fonction printf, qui n'a décidemment pas fini de nous étonner, peut aussi afficher un caractère. Pour cela, on doit utiliser le symbole %c (c comme caractère) :
Code : C1
2
3
4
5
6
7
8int main(int argc, char *argv[])
{
char lettre = 'A';
printf("%c\n", lettre);
return 0;
}
Code : Console
A
Hourra !
Nous savons afficher une lettre
On peut aussi demander à l'utilisateur de rentrer une lettre en utilisant le %c dans un scanf :
Code : C1
2
3
4
5
6
7
8
9int main(int argc, char *argv[])
{
char lettre = 0;
scanf("%c", &lettre);
printf("%c\n", lettre);
return 0;
}
Si je tape la lettre B, je verrai :
Code : Console
B
B
(le premier des 2 B étant celui que j'ai tapé au clavier, et le second étant affiché par le printf)
Voici à peu près tout ce qu'il faut savoir sur le type char. Il cachait décidemment bien son jeu celui-là
Retenez bien :
Les chaînes sont des tableaux de char !
Arf, j'ai tout dit dans le titre, qu'est-ce que je vais bien pouvoir raconter maintenant
Ben oui, tout y est : une chaîne de caractères n'est rien d'autre qu'un tableau de type char. Un bête tableau de rien du tout
Si on crée un tableau :
Code : C1char chaine[5];
... et qu'on met dans chaine[0] la lettre 'S', dans chaine[1] la lettre 'a', etc... On peut ainsi former une chaîne de caractères, c'est-à-dire du texte
Voici un schéma de la façon dont ça pourrait être stocké en mémoire (attention je vous préviens de suite, c'est un peu plus compliqué que ça en réalité, je vous explique après pourquoi) :
Comme on peut le voir, c'est un tableau qui prend 5 cases en mémoire pour représenter le mot "Salut". Pour la valeur, j'ai mis exprès les lettres entre apostrophes, pour indiquer que c'est un nombre qui est stocké et non une lettre. En réalité, dans la mémoire ce sont bel et bien les valeurs de ces lettres qui sont stockées
Oui mais attention, une chaîne de caractères ne contient pas que des lettres ! Le schéma que vous voyez ci-dessus est en fait incomplet.
Une chaîne de caractère doit impérativement contenir un caractère spécial à la fin de la chaîne, appelé "Caractère de fin de chaîne". Ce caractère s'écrit '\0'.
Pourquoi devoir terminer une chaîne de caractères par un \0 ?
Tout simplement pour que votre ordinateur sache quand s'arrête la chaîne ! Le caractère \0 permet de dire : "Stop, c'est fini, y'a plus rien à lire après circulez !"
Par conséquent, pour stocker le mot "Salut" (qui comprend 5 lettres) en mémoire, il ne faut pas un tableau de 5 char, il faut un tableau de 6 char !
A chaque fois que vous créez une chaîne de caractères, vous allez donc devoir penser à prévoir de la place pour le caractère de fin de chaîne. Il faut toujours toujours toujours rajouter un bloc de plus dans le tableau pour stocker ce caractère \0, c'est impératif !
Oublier le caractère de fin \0, c'est une source d'erreurs impitoyable du langage C. Je le sais, j'en ai fait les frais et pas qu'une fois
En clair, le bon schéma de la chaîne de caractères "Salut" en mémoire est le suivant :
Comme vous le voyez, la chaîne prend 6 caractères et non pas 5, il va falloir s'y faire
La chaîne se termine par '\0', le caractère de fin de chaîne qui permet d'indiquer à l'ordinateur que la chaîne se termine là.
Voyez le caractère \0 comme un avantage. Grâce à lui, vous n'aurez pas à retenir la taille de votre tableau car il indique que le tableau s'arrête là
Vous pourrez passer votre tableau de char à une fonction sans avoir à ajouter à côté une variable indiquant la taille du tableau.
Cela n'est valable que pour les chaînes de caractères (c'est-à-dire le type char*, qu'on peut aussi écrire char[] ). Pour les autres types de tableaux, vous êtes toujours obligés de retenir la taille du tableau quelque part.
Création et initialisation de la chaîne
Si on veut initialiser notre tableau chaine avec le texte "Salut", on peut utiliser la méthode old-school un peu bourrin :
Code : C1
2
3
4
5
6
7
8char chaine[6]; // Tableau de 6 char pour stocker S-a-l-u-t + le \0
chaine[0] = 'S';
chaine[1] = 'a';
chaine[2] = 'l';
chaine[3] = 'u';
chaine[4] = 't';
chaine[5] = '\0';
Cette méthode marche.
On peut le vérifier en faisant un printf.
Ah oui, j'allais oublier le printf : y'a encore un nouveau symbole à retenir
C'est le %s (s comme string, qui signifie "chaîne" en anglais).
Voici le code complet qui crée une chaîne "Salut" en mémoire et qui l'affiche :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char chaine[6]; // Tableau de 6 char pour stocker S-a-l-u-t + le \0
// Initialisation de la chaîne (on écrit les caractères 1 à 1 en mémoire)
chaine[0] = 'S';
chaine[1] = 'a';
chaine[2] = 'l';
chaine[3] = 'u';
chaine[4] = 't';
chaine[5] = '\0';
// Affichage de la chaîne grâce au %s du printf
printf("%s", chaine);
return 0;
}
Résultat :
Code : Console
Salut
Pfiou
Tout ça pour stocker "Salut" en mémoire et l'afficher quand même
C'est un peu fatigant et répétitif de devoir écrire les caractères un à un comme on l'a fait dans le tableau chaine.
Pour initialiser une chaîne, il existe heureusement une méthode plus simple :
Code : C1
2
3
4
5
6
7
8
9int main(int argc, char *argv[])
{
char chaine[] = "Salut"; // La taille du tableau chaine est automatiquement calculée
printf("%s", chaine);
return 0;
}
Code : Console
Salut
Comme vous le voyez à la première ligne, je crée une variable de type char[]. J'aurais pu écrire aussi char*, le résultat aurait été le même.
En tapant entre guillemets la chaîne que vous voulez mettre dans votre tableau, le compilateur C calcule automatiquement la taille nécessaire. C'est-à-dire qu'il compte les lettres et rajoute 1 pour placer le caractère \0. Il écrit ensuite une à une les lettres du mot "Salut" en mémoire et rajoute l'\0 comme on l'a fait nous-mêmes manuellement quelques instants plus tôt.
Bref, c'est bien pratique
Défaut : ça ne marche que pour l'initialisation ! Vous ne pouvez pas écrire plus loin dans le code :
Code : C1chaine = "Salut";
Cette technique est donc à réserver à l'initialisation. Après cela, il faudra écrire les caractères manuellement un à un en mémoire
Récupération d'une chaîne via un scanf
Vous pouvez enregistrer une chaîne rentrée par l'utilisateur via un scanf, en utilisant là encore le symbole %s.
Seul problème : vous ne savez pas combien de caractères l'utilisateur va rentrer. Si vous lui demandez son prénom, il s'appelle peut-être Luc (3 caractères), mais qui vous dit qu'il ne s'appelle pas Jean-Edouard (beaucoup plus de caractères) ?
Pour ça, il n'y a pas 36 solutions. Il va falloir créer un tableau de char très grand, suffisamment grand pour pouvoir stocker le prénom. On va donc créer un char[100] pour stocker le prénom. Ca donne l'impression de gâcher de la mémoire, mais souvenez-vous encore une fois que de la place en mémoire c'est pas ce qui manque (et y'a des programmes qui gâchent de la mémoire de manière bien pire que ça, si vous saviez
)
Code : C 1
2
3
4
5
6
7
8
9
10int main(int argc, char *argv[])
{
char prenom[100];
printf("Comment t'appelles-tu petit Zer0 ? ");
scanf("%s", prenom);
printf("Salut %s, je suis heureux de te rencontrer !", prenom);
return 0;
}
Code : Console
Comment t'appelles-tu petit Zer0 ? Mateo21
Salut Mateo21, je suis heureux de te rencontrer !
Voilà en gros comment ça se passe pour demander d'entrer du texte à l'utilisateur
Fonctions de manipulation des chaînes
Les chaînes de caractères sont, vous vous en doutez, fréquemment utilisées. Tous les mots, tous les textes que vous voyez à votre écran sont en fait des tableaux de char en mémoire qui fonctionnent de la manière que je viens de vous expliquer (ah on ne voit plus son ordinateur de la même façon du coup hein ?
)
Afin de nous aider un peu à manipuler les chaînes, on nous fournit dans la bibliothèque string.h une pléthore de fonctions dédiées aux calculs sur des chaînes.
Je ne peux pas vraiment toutes vous les présenter ici, ce serait un peu long et elles ne sont pas toutes forcément indispensables.
Je vais me contenter de vous parler des principales dont vous aurez très certainement besoin dans peu de temps, ce qui fait déjà pas mal
Pensez à inclure string.h
Même si cela devrait vous paraître évident, je préfère vous le préciser encore au cas où : comme on va utiliser une nouvelle bibliothèque appelée string.h, vous devez l'inclure en haut des fichiers .c où vous en avez besoin :
Code : C1#include <string.h>
Si vous ne le faites pas, l'ordinateur ne connaîtra pas les fonctions que je vais vous présenter car il n'aura pas les prototypes, et la compilation plantera.
Bref, n'oubliez pas d'inclure cette bibliothèque à chaque fois que vous utilisez des fonctions de manipulation de chaînes
strlen : calculer la longueur d'une chaîne
strlen est une fonction qui calcule la longueur d'une chaîne de caractères (sans compter le caractère \0 ).
Vous devez lui envoyer un seul paramètre : votre chaîne de caractères ! Cette fonction vous retourne la longueur de la chaîne.
Maintenant que vous savez ce qu'est un prototype, je vais vous donner le prototype des fonctions dont je vous parle. Les programmeurs s'en servent comme "mode d'emploi" de la fonction (même si quelques explications à côté ne sont jamais superflues
) :
Code : C1size_t strlen(const char* chaine);
size_t est un type spécial qui signifie que la fonction renvoie un nombre correspondant à une taille. Ce n'est pas un type de base comme int, long ou char, c'est un type "inventé". Nous apprendrons nous aussi à créer nos propres types de variables quelques chapitres plus loin.
Pour le moment, on va se contenter de stocker la valeur renvoyée par strlen dans une variable de type int (l'ordinateur convertira de size_t en int automatiquement). En toute rigueur, il faudrait plutôt stocker le résultat dans une variable de type size_t, mais en pratique un int est suffisant pour cela.
La fonction prend un paramètre de type const char*. Le const (qui signifie constante, rappelez-vous) fait que la fonction strlen "s'interdit" en quelque sorte de modifier votre chaîne. Quand vous voyez un const, vous savez que la variable n'est pas modifiée par la fonction, elle est juste lue.
Testons la fonction strlen :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13int main(int argc, char *argv[])
{
char chaine[] = "Salut";
int longueurChaine = 0;
// On récupère la longueur de la chaîne dans longueurChaine
longueurChaine = strlen(chaine);
// On affiche la longueur de la chaîne
printf("La chaine %s fait %d caracteres de long", chaine, longueurChaine);
return 0;
}
Code : Console
La chaine Salut fait 5 caracteres de long
Cette fonction strlen est d'ailleurs facile à écrire. Il suffit de faire une boucle sur le tableau de char qui s'arrête quand on tombe sur le caractère \0. Un compteur s'incrémente à chaque tour de boucle, et c'est ce compteur que la fonction retourne.
Allez, ça m'a donné envie d'écrire moi-même une fonction similaire à strlen
Ca vous permettra en plus de bien comprendre comment la fonction marche :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30int longueurChaine(const char* chaine);
int main(int argc, char *argv[])
{
char chaine[] = "Salut";
int longueur = 0;
longueur = longueurChaine(chaine);
printf("La chaine %s fait %d caracteres de long", chaine, longueur);
return 0;
}
int longueurChaine(const char* chaine)
{
int nombreDeCaracteres = 0;
char caractereActuel = 0;
do
{
caractereActuel = chaine[nombreDeCaracteres];
nombreDeCaracteres++;
}
while(caractereActuel != '\0'); // On boucle tant qu'on n'est pas arrivé à l'\0
nombreDeCaracteres--; // On retire 1 caractère de long pour ne pas compter l'\0
return nombreDeCaracteres;
}
La fonction longueurChaine fait une boucle sur le tableau chaine. Elle stocke les caractères un par un dans caractereActuel. Dès que caractèreActuel vaut '\0', la boucle s'arrête.
A chaque passage dans la boucle, on ajoute 1 au nombre de caractères qu'on a analysé.
A la fin de la boucle, on retire 1 caractère au nombre total de caractères qu'on a comptés. Cela permet de ne pas compter le caractère \0 dans le lot.
Enfin, on retourne nombreDeCaracteres, et le tour est joué
strcpy : copier une chaîne dans une autre
La fonction strcpy (comme "string copy") permet de copier une chaîne à l'intérieur d'une autre.
Son prototype est :
Code : C1char* strcpy(char* copieDeLaChaine, const char* chaineACopier);
Cette fonction prend 2 paramètres :
La fonction renvoie un pointeur sur copieDeLaChaine, ce qui n'est pas très utile. En général, on ne récupère pas ce que cette fonction renvoie.
Allons tester ça :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16int main(int argc, char *argv[])
{
/* On crée une chaine "chaine" qui contient un peu de texte
et une copie (vide) de taille 100 pour être sûr d'avoir la place
pour la copie */
char chaine[] = "Texte", copie[100] = {0};
strcpy(copie, chaine); // On copie "chaine" dans "copie"
// Si tout s'est bien passé, la copie devrait être identique à chaine
printf("chaine vaut : %s\n", chaine);
printf("copie vaut : %s\n", copie);
return 0;
}
Code : Console
chaine vaut : Texte
copie vaut : Texte
On voit que chaine vaut "Texte". Bon ça c'est normal
Par contre, on voit aussi que la variable copie, qui était vide au départ, a été remplie par le contenu de chaine. La chaine a donc bien été copiée dans "copie"
Vérifiez que la chaîne "copie" est assez grande pour accueillir le contenu de "chaine". Si, dans mon exemple, j'avais défini copie[5] (ce qui n'est pas suffisant car il n'y aurait pas eu de place pour l'\0), la fonction strcpy aurait "débordé en mémoire" et probablement fait planter votre programme. A éviter à tout prix, sauf si vous aimez faire crasher votre ordinateur bien sûr
Schématiquement, il s'est passé ça en mémoire :
Chaque caractère de chaine a été placé dans copie.
La chaîne copie contient de nombreux caractères inutilisés, vous l'aurez remarqué. Je lui ai donné la taille 100 par sécurité, mais en toute rigueur la taille 6 aurait suffit. L'avantage de créer un tableau un peu plus grand, c'est que de cette façon la chaîne copie sera capable de recevoir d'autres chaînes peut-être plus grandes dans la suite du programme.
strcat : concaténer 2 chaînes
Cette fonction ajoute une chaîne à la suite d'une autre. On appelle cela la concaténation.
Si j'ai :
Si je concatène chaine2 dans chaine1, alors chaine1 vaudra "Salut Mateo21".
chaine2, elle, n'aura pas changé et vaudra donc toujours "Mateo21". Seule chaine1 est modifiée.
C'est exactement ce que fait strcat, dont voici le prototype :
Code : C1char* strcat(char* chaine1, const char* chaine2);
Comme vous pouvez le voir, chaine2 ne peut pas être modifiée car elle est définie comme constante dans le prototype de la fonction.
La fonction retourne un pointeur vers chaine1 ce qui, comme pour strcpy, ne sert pas à grand-chose dans le cas présent, donc on peut ignorer ce que la fonction nous renvoie.
La fonction ajoute à chaine1 le contenu de chaine2. Regardons-y de plus près :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15int main(int argc, char *argv[])
{
/* On crée 2 chaînes. chaine1 doit être assez grande pour accueillir
le contenu de chaine2 en plus, sinon risque de plantage */
char chaine1[100] = "Salut ", chaine2[] = "Mateo21";
strcat(chaine1, chaine2); // On concatène chaine2 dans chaine1
// Si tout s'est bien passé, chaine1 vaut "Salut Mateo21"
printf("chaine1 vaut : %s\n", chaine1);
// chaine2 n'a pas changé :
printf("chaine2 vaut toujours : %s\n", chaine2);
return 0;
}
Code : Console
chaine1 vaut : Salut Mateo21
chaine2 vaut toujours : Mateo21
Vérifiez absolument que chaine1 est assez grande pour qu'on puisse lui rajouter le contenu de chaine2, sinon vous ferez un débordement en mémoire qui peut conduire à un plantage.
C'est pour cela que j'ai défini chaine1 de taille 100. Quant à chaine2, j'ai laissé l'ordinateur calculer sa taille (je n'ai donc pas précisé la taille) car cette chaîne n'est pas modifiée, il n'y a donc pas besoin de la rendre plus grande que nécessaire
Schématiquement il s'est passé ça :
Le tableau chaine2 a été ajouté à la suite de chaine1 (qui comprenait une centaine de cases)
L'\0 de chaine1 a été supprimé (en fait il a été remplacé par le M de Mateo21). En effet, il ne faut pas laisser un \0 au milieu de la chaîne sinon celle-ci aurait été "coupée" au milieu ! On ne met qu'un \0 à la fin de la chaîne, une fois qu'elle est finie.
strcmp : comparer 2 chaînes
strcmp compare 2 chaînes entre elles. Voici son prototype :
Code : C1int strcmp(const char* chaine1, const char* chaine2);
Les variables chaine1 et chaine2 sont comparées. Comme vous le voyez, aucune d'elles n'est modifiée car elles sont indiquées comme constantes.
Il est important de récupérer ce que la fonction renvoie. En effet, strcmp renvoie :
Il aurait été plus logique, je le reconnais, que la fonction renvoie 1 si les chaînes sont identiques pour dire "vrai" (rappelez-vous des booléens). Toutefois, comme ce n'est pas moi qui ai codé la fonction...
Plus sérieusement, la fonction compare les valeurs de chacun des caractères un à un. Si tous les caractères sont identiques, elle renvoie 0. Si les caractères de la chaine1 sont supérieurs à ceux de la chaine2, la fonction renvoie un nombre positif. Si c'est l'inverse, la fonction renvoie un nombre négatif.
Dans la pratique, on se sert surtout de strcmp pour vérifier si 2 chaînes sont identiques, point barre
Voici un code de test :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15int main(int argc, char *argv[])
{
char chaine1[] = "Texte de test", chaine2[] = "Texte de test";
if (strcmp(chaine1, chaine2) == 0) // Si strcmp renvoie 0 (chaînes identiques)
{
printf("Les chaines sont identiques\n");
}
else
{
printf("Les chaines sont differentes\n");
}
return 0;
}
Code : Console
Les chaines sont identiques
Les chaînes étant identiques, la fonction strcmp a renvoyé le nombre 0.
Notez que j'aurais pu stocker ce que renvoie strcmp dans une variable de type int. Toutefois, ce n'est pas obligatoire, on peut directement mettre la fonction dans le if comme je l'ai fait.
Je n'ai pas grand-chose à rajouter à propos de cette fonction. Elle est assez simple à utiliser en fait, mais il ne faut pas oublier que 0 signifie "identique" et une autre valeur signifie "différent". C'est la seule source d'erreurs possible ici.
strchr : rechercher un caractère
La fonction strchr recherche un caractère dans une chaîne.
Prototype :
Code : C1char* strchr(const char* chaine, int caractereARechercher);
La fonction prend 2 paramètres :
Vous remarquerez que caractereARechercher est de type int et non de type char. Ce n'est pas réellement un problème car, au fond, un caractère est et restera toujours un nombre
Néanmoins, on utilise quand même plus souvent un char qu'un int pour stocker un caractère en mémoire.
La fonction renvoie un pointeur vers le premier caractère qu'elle a trouvé, c'est-à-dire qu'elle renvoie l'adresse de ce caractère dans la mémoire. Elle renvoie NULL si elle n'a rien trouvé.
Dans l'exemple suivant, je récupère ce pointeur dans suiteChaine :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12int main(int argc, char *argv[])
{
char chaine[] = "Texte de test", *suiteChaine = NULL;
suiteChaine = strchr(chaine, 'd');
if (suiteChaine != NULL) // Si on a trouvé quelque chose
{
printf("Voici la fin de la chaine a partir du premier d : %s", suiteChaine);
}
return 0;
}
Code : Console
Voici la fin de la chaine a partir du premier d : de test
Avez-vous bien compris ce qu'il se passe ici ? C'est un peu particulier.
En fait, suiteChaine est un pointeur comme chaine. Sauf que chaine pointe sur le premier caractère (le 'T' majuscule), tandis que suiteChaine pointe sur le premier caractère 'd' qui a été trouvé dans chaine.
Le schéma suivant vous montre où pointe chaque pointeur :
chaine commence au début de la chaine ('T' majuscule), tandis que suiteChaine pointe sur le 'd' minuscule.
Lorsque je fais un printf de suiteChaine, il est donc normal que l'on m'affiche juste "de test". La fonction printf affiche tous les caractères qu'elle rencontre ('d', 'e', ' ', 't', 'e', 's', 't') jusqu'à ce qu'elle tombe sur l'\0 qui lui dit que la chaîne s'arrête là.
Variante
Il existe une fonction strrchr strictement identique à strchr, sauf que celle-là renvoie un pointeur vers le dernier caractère qu'elle a trouvé dans la chaîne au lieu du premier
strpbrk : premier caractère de la liste
Cette fonction ressemble beaucoup à la précédente. Celle-ci recherche un des caractères dans la liste que vous lui donnez sous forme de chaîne, contrairement à strchr qui ne peut rechercher qu'un seul caractère à la fois.
Par exemple, si on forme la chaîne "xds" et qu'on en fait une recherche dans "Texte de test", la fonction renvoie un pointeur vers le premier de ces caractères qu'elle a trouvé dedans. En l'occurrence, le premier caractère de "xds" qu'elle trouve dans "Texte de test" est le x, donc strpbrk renverra un pointeur sur 'x'.
Prototype :
Code : C1char* strpbrk(const char* chaine, const char* lettresARechercher);
Test :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14int main(int argc, char *argv[])
{
char *suiteChaine;
// On cherche la première occurrence de x, d ou s dans "Texte de test"
suiteChaine = strpbrk("Texte de test", "xds");
if (suiteChaine != NULL)
{
printf("Voici la fin de la chaine a partir du premier des caracteres trouves : %s", suiteChaine);
}
return 0;
}
Code : Console
Voici la fin de la chaine a partir du premier des caracteres trouves : xte de test
Pour cet exemple, j'ai directement écrit les valeurs à envoyer à la fonction (entre guillemets). On n'est en effet pas obligés d'employer une variable à tous les coups, on peut très bien écrire la chaîne directement.
Il faut simplement retenir la règle suivante :
strstr : rechercher une chaîne dans une autre
Cette fonction recherche la première occurrence d'une chaîne dans une autre chaîne.
Son prototype est :
Code : C1char* strstr(const char* chaine, const char* chaineARechercher);
Le prototype est similaire à strpbrk, mais attention à ne pas confondre : strpbrk recherche UN des caractères, tandis que strstr recherche toute la chaîne.
Exemple :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13int main(int argc, char *argv[])
{
char *suiteChaine;
// On cherche la première occurrence de "test" dans "Texte de test" :
suiteChaine = strstr("Texte de test", "test");
if (suiteChaine != NULL)
{
printf("Premiere occurence de test dans Texte de test : %s\n", suiteChaine);
}
return 0;
}
Code : Console
Premiere occurence de test dans Texte de test : test
La fonction strstr recherche la chaîne "test" dans "Texte de test".
Elle renvoie, comme les autres, un pointeur quand elle a trouvé ce qu'elle cherchait. Elle renvoie NULL si elle n'a rien trouvé.
Pensez à vérifier si vos fonctions de recherche n'ont pas renvoyé NULL. Si vous ne le faites pas et que vous essayez d'afficher une chaîne qui pointe sur NULL, votre programme plantera. Votre OS fermera brutalement votre programme car il aura essayé d'accéder à l'adresse NULL à laquelle il n'a pas le droit d'accéder.
Jusqu'ici, je me suis contenté d'afficher la chaîne à partir du pointeur retourné par les fonctions. Dans la pratique, ça n'est pas très utile
Vous ferez juste un if (resultat != NULL) pour savoir si la recherche a trouvé quelque chose ou si elle n'a rien trouvé, et vous afficherez "Le texte que vous recherchiez a été trouvé".
Enfin, cela dépend de votre programme, mais en tout cas ces fonctions sont la base si vous voulez faire un traitement de texte
sprintf : écrire dans une chaîne
Cette fonction se trouve dans stdio.h contrairement aux autres fonctions que nous avons étudiées jusqu'ici, qui étaient dans string.h
Ce nom doit vaguement vous rappeler quelque chose
Cette fonction ressemble énormément au printf que vous connaissez mais, au lieu d'écrire à l'écran, sprintf écrit dans... une chaîne ! D'où son nom d'ailleurs, qui commence par le "s" de "string" (chaîne en anglais).
C'est une fonction très pratique pour mettre en forme une chaîne. Petit exemple :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char chaine[100];
int age = 15;
// On écrit "Tu as 15 ans" dans chaine
sprintf(chaine, "Tu as %d ans !", age);
// On affiche chaine pour vérifier qu'elle contient bien cela :
printf("%s", chaine);
return 0;
}
Code : Console
Tu as 15 ans !
Elle s'utilise de la même manière que printf, mis à part le fait que vous devez lui donner en premier paramètre un pointeur vers la chaîne qui doit recevoir le texte.
Dans mon exemple, j'écris dans chaine "Tu as %d ans", où %d est remplacé par le contenu de la variable age. Toutes les règles du printf s'appliquent, vous pouvez donc si vous le voulez mettre des %s pour insérer d'autres chaînes à l'intérieur de votre chaîne
Comme d'hab, vérifiez que votre chaîne est suffisamment grande pour accueillir tout le texte que le sprintf va lui envoyer. Sinon, ben... boum
Dans ce chapitre, nous allons porter une attention particulière au type char.
Si vous vous souvenez bien, le type char permet de stocker des nombres compris entre -128 et 127.
Si ce type char permet de stocker des nombres, il faut savoir qu'en C on l'utilise rarement pour ça. En général, même si le nombre est petit, on le stocke dans un long ou un int. Certes, ça prend un peu plus de place en mémoire, mais aujourd'hui la mémoire c'est vraiment pas ce qui manque sur un ordinateur
![clin.png](http://www.siteduzero.com/Templates/images/smilies/clin.png)
![langue.png](http://www.siteduzero.com/Templates/images/smilies/langue.png)
Le type char est en fait prévu pour stocker... une lettre !
Attention, j'ai bien dit : UNE lettre.
Comme la mémoire ne peut stocker que des nombres, on a inventé une table qui fait la conversion entre les nombres et les lettres. Cette table indique ainsi par exemple que le nombre 65 équivaut à la lettre A.
Le langage C permet de faire très facilement la traduction : lettre => nombre correspondant. Pour obtenir le nombre associé à une lettre, il suffit de mettre cette lettre entre apostrophes, comme ceci : 'A'. A la compilation, 'A' sera remplacé par la valeur correspondante.
Testons :
Code : C1
2
3
4
5
6
7
8int main(int argc, char *argv[])
{
char lettre = 'A';
printf("%d\n", lettre);
return 0;
}
Code : Console
65
On sait donc que la lettre A majuscule est représentée par le nombre 65. B vaut 66, C vaut 67 etc.
Testez avec des minuscules, et vous verrez que les valeurs sont différentes. En effet, la lettre 'a' n'est pas identique à la lettre 'A', l'ordinateur faisant la différence entre les majuscules et les minuscules.
La plupart des caractères "de base" sont codés entre les nombres 0 et 127.
Afficher un caractère
La fonction printf, qui n'a décidemment pas fini de nous étonner, peut aussi afficher un caractère. Pour cela, on doit utiliser le symbole %c (c comme caractère) :
Code : C1
2
3
4
5
6
7
8int main(int argc, char *argv[])
{
char lettre = 'A';
printf("%c\n", lettre);
return 0;
}
Code : Console
A
Hourra !
Nous savons afficher une lettre
![heureux.png](http://www.siteduzero.com/Templates/images/smilies/heureux.png)
On peut aussi demander à l'utilisateur de rentrer une lettre en utilisant le %c dans un scanf :
Code : C1
2
3
4
5
6
7
8
9int main(int argc, char *argv[])
{
char lettre = 0;
scanf("%c", &lettre);
printf("%c\n", lettre);
return 0;
}
Si je tape la lettre B, je verrai :
Code : Console
B
B
(le premier des 2 B étant celui que j'ai tapé au clavier, et le second étant affiché par le printf)
Voici à peu près tout ce qu'il faut savoir sur le type char. Il cachait décidemment bien son jeu celui-là
![clin.png](http://www.siteduzero.com/Templates/images/smilies/clin.png)
Retenez bien :
- Le type char permet de stocker des nombres allant de -128 à 127, unsigned char des nombres de 0 à 255.
- Il y a une table que votre ordinateur utilise pour convertir les lettres en nombres et inversement.
- On peut donc utiliser le type char pour stocker UNE lettre.
- 'A' est remplacé à la compilation par la valeur correspondante (65 en l'occurrence). On utilise donc les apostrophes pour obtenir la valeur d'une lettre.
Les chaînes sont des tableaux de char !
Arf, j'ai tout dit dans le titre, qu'est-ce que je vais bien pouvoir raconter maintenant
![rire.gif](http://www.siteduzero.com/Templates/images/smilies/rire.gif)
Ben oui, tout y est : une chaîne de caractères n'est rien d'autre qu'un tableau de type char. Un bête tableau de rien du tout
![clin.png](http://www.siteduzero.com/Templates/images/smilies/clin.png)
Si on crée un tableau :
Code : C1char chaine[5];
... et qu'on met dans chaine[0] la lettre 'S', dans chaine[1] la lettre 'a', etc... On peut ainsi former une chaîne de caractères, c'est-à-dire du texte
![smile.png](http://www.siteduzero.com/Templates/images/smilies/smile.png)
Voici un schéma de la façon dont ça pourrait être stocké en mémoire (attention je vous préviens de suite, c'est un peu plus compliqué que ça en réalité, je vous explique après pourquoi) :
![8630.png](http://www.siteduzero.com/uploads/fr/files/8001_9000/8630.png)
Comme on peut le voir, c'est un tableau qui prend 5 cases en mémoire pour représenter le mot "Salut". Pour la valeur, j'ai mis exprès les lettres entre apostrophes, pour indiquer que c'est un nombre qui est stocké et non une lettre. En réalité, dans la mémoire ce sont bel et bien les valeurs de ces lettres qui sont stockées
![clin.png](http://www.siteduzero.com/Templates/images/smilies/clin.png)
Oui mais attention, une chaîne de caractères ne contient pas que des lettres ! Le schéma que vous voyez ci-dessus est en fait incomplet.
Une chaîne de caractère doit impérativement contenir un caractère spécial à la fin de la chaîne, appelé "Caractère de fin de chaîne". Ce caractère s'écrit '\0'.
Pourquoi devoir terminer une chaîne de caractères par un \0 ?
Tout simplement pour que votre ordinateur sache quand s'arrête la chaîne ! Le caractère \0 permet de dire : "Stop, c'est fini, y'a plus rien à lire après circulez !"
Par conséquent, pour stocker le mot "Salut" (qui comprend 5 lettres) en mémoire, il ne faut pas un tableau de 5 char, il faut un tableau de 6 char !
A chaque fois que vous créez une chaîne de caractères, vous allez donc devoir penser à prévoir de la place pour le caractère de fin de chaîne. Il faut toujours toujours toujours rajouter un bloc de plus dans le tableau pour stocker ce caractère \0, c'est impératif !
Oublier le caractère de fin \0, c'est une source d'erreurs impitoyable du langage C. Je le sais, j'en ai fait les frais et pas qu'une fois
![heureux.png](http://www.siteduzero.com/Templates/images/smilies/heureux.png)
En clair, le bon schéma de la chaîne de caractères "Salut" en mémoire est le suivant :
![8631.png](http://www.siteduzero.com/uploads/fr/files/8001_9000/8631.png)
Comme vous le voyez, la chaîne prend 6 caractères et non pas 5, il va falloir s'y faire
![clin.png](http://www.siteduzero.com/Templates/images/smilies/clin.png)
La chaîne se termine par '\0', le caractère de fin de chaîne qui permet d'indiquer à l'ordinateur que la chaîne se termine là.
Voyez le caractère \0 comme un avantage. Grâce à lui, vous n'aurez pas à retenir la taille de votre tableau car il indique que le tableau s'arrête là
![smile.png](http://www.siteduzero.com/Templates/images/smilies/smile.png)
Cela n'est valable que pour les chaînes de caractères (c'est-à-dire le type char*, qu'on peut aussi écrire char[] ). Pour les autres types de tableaux, vous êtes toujours obligés de retenir la taille du tableau quelque part.
Création et initialisation de la chaîne
Si on veut initialiser notre tableau chaine avec le texte "Salut", on peut utiliser la méthode old-school un peu bourrin :
Code : C1
2
3
4
5
6
7
8char chaine[6]; // Tableau de 6 char pour stocker S-a-l-u-t + le \0
chaine[0] = 'S';
chaine[1] = 'a';
chaine[2] = 'l';
chaine[3] = 'u';
chaine[4] = 't';
chaine[5] = '\0';
Cette méthode marche.
On peut le vérifier en faisant un printf.
Ah oui, j'allais oublier le printf : y'a encore un nouveau symbole à retenir
![hihi.png](http://www.siteduzero.com/Templates/images/smilies/hihi.png)
C'est le %s (s comme string, qui signifie "chaîne" en anglais).
Voici le code complet qui crée une chaîne "Salut" en mémoire et qui l'affiche :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char chaine[6]; // Tableau de 6 char pour stocker S-a-l-u-t + le \0
// Initialisation de la chaîne (on écrit les caractères 1 à 1 en mémoire)
chaine[0] = 'S';
chaine[1] = 'a';
chaine[2] = 'l';
chaine[3] = 'u';
chaine[4] = 't';
chaine[5] = '\0';
// Affichage de la chaîne grâce au %s du printf
printf("%s", chaine);
return 0;
}
Résultat :
Code : Console
Salut
Pfiou
![hihi.png](http://www.siteduzero.com/Templates/images/smilies/hihi.png)
Tout ça pour stocker "Salut" en mémoire et l'afficher quand même
![heureux.png](http://www.siteduzero.com/Templates/images/smilies/heureux.png)
C'est un peu fatigant et répétitif de devoir écrire les caractères un à un comme on l'a fait dans le tableau chaine.
Pour initialiser une chaîne, il existe heureusement une méthode plus simple :
Code : C1
2
3
4
5
6
7
8
9int main(int argc, char *argv[])
{
char chaine[] = "Salut"; // La taille du tableau chaine est automatiquement calculée
printf("%s", chaine);
return 0;
}
Code : Console
Salut
Comme vous le voyez à la première ligne, je crée une variable de type char[]. J'aurais pu écrire aussi char*, le résultat aurait été le même.
En tapant entre guillemets la chaîne que vous voulez mettre dans votre tableau, le compilateur C calcule automatiquement la taille nécessaire. C'est-à-dire qu'il compte les lettres et rajoute 1 pour placer le caractère \0. Il écrit ensuite une à une les lettres du mot "Salut" en mémoire et rajoute l'\0 comme on l'a fait nous-mêmes manuellement quelques instants plus tôt.
Bref, c'est bien pratique
![smile.png](http://www.siteduzero.com/Templates/images/smilies/smile.png)
Défaut : ça ne marche que pour l'initialisation ! Vous ne pouvez pas écrire plus loin dans le code :
Code : C1chaine = "Salut";
Cette technique est donc à réserver à l'initialisation. Après cela, il faudra écrire les caractères manuellement un à un en mémoire
![hihi.png](http://www.siteduzero.com/Templates/images/smilies/hihi.png)
Récupération d'une chaîne via un scanf
Vous pouvez enregistrer une chaîne rentrée par l'utilisateur via un scanf, en utilisant là encore le symbole %s.
Seul problème : vous ne savez pas combien de caractères l'utilisateur va rentrer. Si vous lui demandez son prénom, il s'appelle peut-être Luc (3 caractères), mais qui vous dit qu'il ne s'appelle pas Jean-Edouard (beaucoup plus de caractères) ?
Pour ça, il n'y a pas 36 solutions. Il va falloir créer un tableau de char très grand, suffisamment grand pour pouvoir stocker le prénom. On va donc créer un char[100] pour stocker le prénom. Ca donne l'impression de gâcher de la mémoire, mais souvenez-vous encore une fois que de la place en mémoire c'est pas ce qui manque (et y'a des programmes qui gâchent de la mémoire de manière bien pire que ça, si vous saviez
![heureux.png](http://www.siteduzero.com/Templates/images/smilies/heureux.png)
Code : C 1
2
3
4
5
6
7
8
9
10int main(int argc, char *argv[])
{
char prenom[100];
printf("Comment t'appelles-tu petit Zer0 ? ");
scanf("%s", prenom);
printf("Salut %s, je suis heureux de te rencontrer !", prenom);
return 0;
}
Code : Console
Comment t'appelles-tu petit Zer0 ? Mateo21
Salut Mateo21, je suis heureux de te rencontrer !
Voilà en gros comment ça se passe pour demander d'entrer du texte à l'utilisateur
![smile.png](http://www.siteduzero.com/Templates/images/smilies/smile.png)
Fonctions de manipulation des chaînes
Les chaînes de caractères sont, vous vous en doutez, fréquemment utilisées. Tous les mots, tous les textes que vous voyez à votre écran sont en fait des tableaux de char en mémoire qui fonctionnent de la manière que je viens de vous expliquer (ah on ne voit plus son ordinateur de la même façon du coup hein ?
![hihi.png](http://www.siteduzero.com/Templates/images/smilies/hihi.png)
Afin de nous aider un peu à manipuler les chaînes, on nous fournit dans la bibliothèque string.h une pléthore de fonctions dédiées aux calculs sur des chaînes.
Je ne peux pas vraiment toutes vous les présenter ici, ce serait un peu long et elles ne sont pas toutes forcément indispensables.
Je vais me contenter de vous parler des principales dont vous aurez très certainement besoin dans peu de temps, ce qui fait déjà pas mal
![clin.png](http://www.siteduzero.com/Templates/images/smilies/clin.png)
Pensez à inclure string.h
Même si cela devrait vous paraître évident, je préfère vous le préciser encore au cas où : comme on va utiliser une nouvelle bibliothèque appelée string.h, vous devez l'inclure en haut des fichiers .c où vous en avez besoin :
Code : C1#include <string.h>
Si vous ne le faites pas, l'ordinateur ne connaîtra pas les fonctions que je vais vous présenter car il n'aura pas les prototypes, et la compilation plantera.
Bref, n'oubliez pas d'inclure cette bibliothèque à chaque fois que vous utilisez des fonctions de manipulation de chaînes
![smile.png](http://www.siteduzero.com/Templates/images/smilies/smile.png)
strlen : calculer la longueur d'une chaîne
strlen est une fonction qui calcule la longueur d'une chaîne de caractères (sans compter le caractère \0 ).
Vous devez lui envoyer un seul paramètre : votre chaîne de caractères ! Cette fonction vous retourne la longueur de la chaîne.
Maintenant que vous savez ce qu'est un prototype, je vais vous donner le prototype des fonctions dont je vous parle. Les programmeurs s'en servent comme "mode d'emploi" de la fonction (même si quelques explications à côté ne sont jamais superflues
![langue.png](http://www.siteduzero.com/Templates/images/smilies/langue.png)
Code : C1size_t strlen(const char* chaine);
size_t est un type spécial qui signifie que la fonction renvoie un nombre correspondant à une taille. Ce n'est pas un type de base comme int, long ou char, c'est un type "inventé". Nous apprendrons nous aussi à créer nos propres types de variables quelques chapitres plus loin.
Pour le moment, on va se contenter de stocker la valeur renvoyée par strlen dans une variable de type int (l'ordinateur convertira de size_t en int automatiquement). En toute rigueur, il faudrait plutôt stocker le résultat dans une variable de type size_t, mais en pratique un int est suffisant pour cela.
La fonction prend un paramètre de type const char*. Le const (qui signifie constante, rappelez-vous) fait que la fonction strlen "s'interdit" en quelque sorte de modifier votre chaîne. Quand vous voyez un const, vous savez que la variable n'est pas modifiée par la fonction, elle est juste lue.
Testons la fonction strlen :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13int main(int argc, char *argv[])
{
char chaine[] = "Salut";
int longueurChaine = 0;
// On récupère la longueur de la chaîne dans longueurChaine
longueurChaine = strlen(chaine);
// On affiche la longueur de la chaîne
printf("La chaine %s fait %d caracteres de long", chaine, longueurChaine);
return 0;
}
Code : Console
La chaine Salut fait 5 caracteres de long
Cette fonction strlen est d'ailleurs facile à écrire. Il suffit de faire une boucle sur le tableau de char qui s'arrête quand on tombe sur le caractère \0. Un compteur s'incrémente à chaque tour de boucle, et c'est ce compteur que la fonction retourne.
Allez, ça m'a donné envie d'écrire moi-même une fonction similaire à strlen
![smile.png](http://www.siteduzero.com/Templates/images/smilies/smile.png)
Ca vous permettra en plus de bien comprendre comment la fonction marche :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30int longueurChaine(const char* chaine);
int main(int argc, char *argv[])
{
char chaine[] = "Salut";
int longueur = 0;
longueur = longueurChaine(chaine);
printf("La chaine %s fait %d caracteres de long", chaine, longueur);
return 0;
}
int longueurChaine(const char* chaine)
{
int nombreDeCaracteres = 0;
char caractereActuel = 0;
do
{
caractereActuel = chaine[nombreDeCaracteres];
nombreDeCaracteres++;
}
while(caractereActuel != '\0'); // On boucle tant qu'on n'est pas arrivé à l'\0
nombreDeCaracteres--; // On retire 1 caractère de long pour ne pas compter l'\0
return nombreDeCaracteres;
}
La fonction longueurChaine fait une boucle sur le tableau chaine. Elle stocke les caractères un par un dans caractereActuel. Dès que caractèreActuel vaut '\0', la boucle s'arrête.
A chaque passage dans la boucle, on ajoute 1 au nombre de caractères qu'on a analysé.
A la fin de la boucle, on retire 1 caractère au nombre total de caractères qu'on a comptés. Cela permet de ne pas compter le caractère \0 dans le lot.
Enfin, on retourne nombreDeCaracteres, et le tour est joué
![clin.png](http://www.siteduzero.com/Templates/images/smilies/clin.png)
strcpy : copier une chaîne dans une autre
La fonction strcpy (comme "string copy") permet de copier une chaîne à l'intérieur d'une autre.
Son prototype est :
Code : C1char* strcpy(char* copieDeLaChaine, const char* chaineACopier);
Cette fonction prend 2 paramètres :
- copieDeLaChaine : c'est un pointeur vers un char* (tableau de char). C'est dans ce tableau que la chaîne sera copiée.
- chaineACopier : c'est un pointeur vers un autre tableau de char. Cette chaîne sera copiée dans copieDeLaChaine.
La fonction renvoie un pointeur sur copieDeLaChaine, ce qui n'est pas très utile. En général, on ne récupère pas ce que cette fonction renvoie.
Allons tester ça :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16int main(int argc, char *argv[])
{
/* On crée une chaine "chaine" qui contient un peu de texte
et une copie (vide) de taille 100 pour être sûr d'avoir la place
pour la copie */
char chaine[] = "Texte", copie[100] = {0};
strcpy(copie, chaine); // On copie "chaine" dans "copie"
// Si tout s'est bien passé, la copie devrait être identique à chaine
printf("chaine vaut : %s\n", chaine);
printf("copie vaut : %s\n", copie);
return 0;
}
Code : Console
chaine vaut : Texte
copie vaut : Texte
On voit que chaine vaut "Texte". Bon ça c'est normal
![hihi.png](http://www.siteduzero.com/Templates/images/smilies/hihi.png)
Par contre, on voit aussi que la variable copie, qui était vide au départ, a été remplie par le contenu de chaine. La chaine a donc bien été copiée dans "copie"
![smile.png](http://www.siteduzero.com/Templates/images/smilies/smile.png)
Vérifiez que la chaîne "copie" est assez grande pour accueillir le contenu de "chaine". Si, dans mon exemple, j'avais défini copie[5] (ce qui n'est pas suffisant car il n'y aurait pas eu de place pour l'\0), la fonction strcpy aurait "débordé en mémoire" et probablement fait planter votre programme. A éviter à tout prix, sauf si vous aimez faire crasher votre ordinateur bien sûr
![smile.png](http://www.siteduzero.com/Templates/images/smilies/smile.png)
Schématiquement, il s'est passé ça en mémoire :
![8633.png](http://www.siteduzero.com/uploads/fr/files/8001_9000/8633.png)
Chaque caractère de chaine a été placé dans copie.
La chaîne copie contient de nombreux caractères inutilisés, vous l'aurez remarqué. Je lui ai donné la taille 100 par sécurité, mais en toute rigueur la taille 6 aurait suffit. L'avantage de créer un tableau un peu plus grand, c'est que de cette façon la chaîne copie sera capable de recevoir d'autres chaînes peut-être plus grandes dans la suite du programme.
strcat : concaténer 2 chaînes
Cette fonction ajoute une chaîne à la suite d'une autre. On appelle cela la concaténation.
Si j'ai :
- chaine1 = "Salut "
- chaine2 = "Mateo21"
Si je concatène chaine2 dans chaine1, alors chaine1 vaudra "Salut Mateo21".
chaine2, elle, n'aura pas changé et vaudra donc toujours "Mateo21". Seule chaine1 est modifiée.
C'est exactement ce que fait strcat, dont voici le prototype :
Code : C1char* strcat(char* chaine1, const char* chaine2);
Comme vous pouvez le voir, chaine2 ne peut pas être modifiée car elle est définie comme constante dans le prototype de la fonction.
La fonction retourne un pointeur vers chaine1 ce qui, comme pour strcpy, ne sert pas à grand-chose dans le cas présent, donc on peut ignorer ce que la fonction nous renvoie.
La fonction ajoute à chaine1 le contenu de chaine2. Regardons-y de plus près :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15int main(int argc, char *argv[])
{
/* On crée 2 chaînes. chaine1 doit être assez grande pour accueillir
le contenu de chaine2 en plus, sinon risque de plantage */
char chaine1[100] = "Salut ", chaine2[] = "Mateo21";
strcat(chaine1, chaine2); // On concatène chaine2 dans chaine1
// Si tout s'est bien passé, chaine1 vaut "Salut Mateo21"
printf("chaine1 vaut : %s\n", chaine1);
// chaine2 n'a pas changé :
printf("chaine2 vaut toujours : %s\n", chaine2);
return 0;
}
Code : Console
chaine1 vaut : Salut Mateo21
chaine2 vaut toujours : Mateo21
Vérifiez absolument que chaine1 est assez grande pour qu'on puisse lui rajouter le contenu de chaine2, sinon vous ferez un débordement en mémoire qui peut conduire à un plantage.
C'est pour cela que j'ai défini chaine1 de taille 100. Quant à chaine2, j'ai laissé l'ordinateur calculer sa taille (je n'ai donc pas précisé la taille) car cette chaîne n'est pas modifiée, il n'y a donc pas besoin de la rendre plus grande que nécessaire
![smile.png](http://www.siteduzero.com/Templates/images/smilies/smile.png)
Schématiquement il s'est passé ça :
![8634.png](http://www.siteduzero.com/uploads/fr/files/8001_9000/8634.png)
Le tableau chaine2 a été ajouté à la suite de chaine1 (qui comprenait une centaine de cases)
L'\0 de chaine1 a été supprimé (en fait il a été remplacé par le M de Mateo21). En effet, il ne faut pas laisser un \0 au milieu de la chaîne sinon celle-ci aurait été "coupée" au milieu ! On ne met qu'un \0 à la fin de la chaîne, une fois qu'elle est finie.
strcmp : comparer 2 chaînes
strcmp compare 2 chaînes entre elles. Voici son prototype :
Code : C1int strcmp(const char* chaine1, const char* chaine2);
Les variables chaine1 et chaine2 sont comparées. Comme vous le voyez, aucune d'elles n'est modifiée car elles sont indiquées comme constantes.
Il est important de récupérer ce que la fonction renvoie. En effet, strcmp renvoie :
- 0 si les chaînes sont identiques
- Une autre valeur (positive ou négative) si les chaînes sont différentes
Il aurait été plus logique, je le reconnais, que la fonction renvoie 1 si les chaînes sont identiques pour dire "vrai" (rappelez-vous des booléens). Toutefois, comme ce n'est pas moi qui ai codé la fonction...
![langue.png](http://www.siteduzero.com/Templates/images/smilies/langue.png)
Plus sérieusement, la fonction compare les valeurs de chacun des caractères un à un. Si tous les caractères sont identiques, elle renvoie 0. Si les caractères de la chaine1 sont supérieurs à ceux de la chaine2, la fonction renvoie un nombre positif. Si c'est l'inverse, la fonction renvoie un nombre négatif.
Dans la pratique, on se sert surtout de strcmp pour vérifier si 2 chaînes sont identiques, point barre
![clin.png](http://www.siteduzero.com/Templates/images/smilies/clin.png)
Voici un code de test :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15int main(int argc, char *argv[])
{
char chaine1[] = "Texte de test", chaine2[] = "Texte de test";
if (strcmp(chaine1, chaine2) == 0) // Si strcmp renvoie 0 (chaînes identiques)
{
printf("Les chaines sont identiques\n");
}
else
{
printf("Les chaines sont differentes\n");
}
return 0;
}
Code : Console
Les chaines sont identiques
Les chaînes étant identiques, la fonction strcmp a renvoyé le nombre 0.
Notez que j'aurais pu stocker ce que renvoie strcmp dans une variable de type int. Toutefois, ce n'est pas obligatoire, on peut directement mettre la fonction dans le if comme je l'ai fait.
Je n'ai pas grand-chose à rajouter à propos de cette fonction. Elle est assez simple à utiliser en fait, mais il ne faut pas oublier que 0 signifie "identique" et une autre valeur signifie "différent". C'est la seule source d'erreurs possible ici.
strchr : rechercher un caractère
La fonction strchr recherche un caractère dans une chaîne.
Prototype :
Code : C1char* strchr(const char* chaine, int caractereARechercher);
La fonction prend 2 paramètres :
- chaine : la chaîne dans laquelle la recherche doit être faite.
- caractereARechercher : le caractère que l'on doit rechercher dans la chaîne.
Vous remarquerez que caractereARechercher est de type int et non de type char. Ce n'est pas réellement un problème car, au fond, un caractère est et restera toujours un nombre
![clin.png](http://www.siteduzero.com/Templates/images/smilies/clin.png)
Néanmoins, on utilise quand même plus souvent un char qu'un int pour stocker un caractère en mémoire.
La fonction renvoie un pointeur vers le premier caractère qu'elle a trouvé, c'est-à-dire qu'elle renvoie l'adresse de ce caractère dans la mémoire. Elle renvoie NULL si elle n'a rien trouvé.
Dans l'exemple suivant, je récupère ce pointeur dans suiteChaine :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12int main(int argc, char *argv[])
{
char chaine[] = "Texte de test", *suiteChaine = NULL;
suiteChaine = strchr(chaine, 'd');
if (suiteChaine != NULL) // Si on a trouvé quelque chose
{
printf("Voici la fin de la chaine a partir du premier d : %s", suiteChaine);
}
return 0;
}
Code : Console
Voici la fin de la chaine a partir du premier d : de test
Avez-vous bien compris ce qu'il se passe ici ? C'est un peu particulier.
En fait, suiteChaine est un pointeur comme chaine. Sauf que chaine pointe sur le premier caractère (le 'T' majuscule), tandis que suiteChaine pointe sur le premier caractère 'd' qui a été trouvé dans chaine.
Le schéma suivant vous montre où pointe chaque pointeur :
![8635.png](http://www.siteduzero.com/uploads/fr/files/8001_9000/8635.png)
chaine commence au début de la chaine ('T' majuscule), tandis que suiteChaine pointe sur le 'd' minuscule.
Lorsque je fais un printf de suiteChaine, il est donc normal que l'on m'affiche juste "de test". La fonction printf affiche tous les caractères qu'elle rencontre ('d', 'e', ' ', 't', 'e', 's', 't') jusqu'à ce qu'elle tombe sur l'\0 qui lui dit que la chaîne s'arrête là.
Variante
Il existe une fonction strrchr strictement identique à strchr, sauf que celle-là renvoie un pointeur vers le dernier caractère qu'elle a trouvé dans la chaîne au lieu du premier
![clin.png](http://www.siteduzero.com/Templates/images/smilies/clin.png)
strpbrk : premier caractère de la liste
Cette fonction ressemble beaucoup à la précédente. Celle-ci recherche un des caractères dans la liste que vous lui donnez sous forme de chaîne, contrairement à strchr qui ne peut rechercher qu'un seul caractère à la fois.
Par exemple, si on forme la chaîne "xds" et qu'on en fait une recherche dans "Texte de test", la fonction renvoie un pointeur vers le premier de ces caractères qu'elle a trouvé dedans. En l'occurrence, le premier caractère de "xds" qu'elle trouve dans "Texte de test" est le x, donc strpbrk renverra un pointeur sur 'x'.
Prototype :
Code : C1char* strpbrk(const char* chaine, const char* lettresARechercher);
Test :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14int main(int argc, char *argv[])
{
char *suiteChaine;
// On cherche la première occurrence de x, d ou s dans "Texte de test"
suiteChaine = strpbrk("Texte de test", "xds");
if (suiteChaine != NULL)
{
printf("Voici la fin de la chaine a partir du premier des caracteres trouves : %s", suiteChaine);
}
return 0;
}
Code : Console
Voici la fin de la chaine a partir du premier des caracteres trouves : xte de test
Pour cet exemple, j'ai directement écrit les valeurs à envoyer à la fonction (entre guillemets). On n'est en effet pas obligés d'employer une variable à tous les coups, on peut très bien écrire la chaîne directement.
Il faut simplement retenir la règle suivante :
- Si vous utilisez les guillemets "", cela signifie chaîne.
- Si vous utilisez les apostrophes '', cela signifie caractère.
strstr : rechercher une chaîne dans une autre
Cette fonction recherche la première occurrence d'une chaîne dans une autre chaîne.
Son prototype est :
Code : C1char* strstr(const char* chaine, const char* chaineARechercher);
Le prototype est similaire à strpbrk, mais attention à ne pas confondre : strpbrk recherche UN des caractères, tandis que strstr recherche toute la chaîne.
Exemple :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13int main(int argc, char *argv[])
{
char *suiteChaine;
// On cherche la première occurrence de "test" dans "Texte de test" :
suiteChaine = strstr("Texte de test", "test");
if (suiteChaine != NULL)
{
printf("Premiere occurence de test dans Texte de test : %s\n", suiteChaine);
}
return 0;
}
Code : Console
Premiere occurence de test dans Texte de test : test
La fonction strstr recherche la chaîne "test" dans "Texte de test".
Elle renvoie, comme les autres, un pointeur quand elle a trouvé ce qu'elle cherchait. Elle renvoie NULL si elle n'a rien trouvé.
Pensez à vérifier si vos fonctions de recherche n'ont pas renvoyé NULL. Si vous ne le faites pas et que vous essayez d'afficher une chaîne qui pointe sur NULL, votre programme plantera. Votre OS fermera brutalement votre programme car il aura essayé d'accéder à l'adresse NULL à laquelle il n'a pas le droit d'accéder.
Jusqu'ici, je me suis contenté d'afficher la chaîne à partir du pointeur retourné par les fonctions. Dans la pratique, ça n'est pas très utile
![clin.png](http://www.siteduzero.com/Templates/images/smilies/clin.png)
Enfin, cela dépend de votre programme, mais en tout cas ces fonctions sont la base si vous voulez faire un traitement de texte
![smile.png](http://www.siteduzero.com/Templates/images/smilies/smile.png)
sprintf : écrire dans une chaîne
Cette fonction se trouve dans stdio.h contrairement aux autres fonctions que nous avons étudiées jusqu'ici, qui étaient dans string.h
Ce nom doit vaguement vous rappeler quelque chose
![hihi.png](http://www.siteduzero.com/Templates/images/smilies/hihi.png)
Cette fonction ressemble énormément au printf que vous connaissez mais, au lieu d'écrire à l'écran, sprintf écrit dans... une chaîne ! D'où son nom d'ailleurs, qui commence par le "s" de "string" (chaîne en anglais).
C'est une fonction très pratique pour mettre en forme une chaîne. Petit exemple :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char chaine[100];
int age = 15;
// On écrit "Tu as 15 ans" dans chaine
sprintf(chaine, "Tu as %d ans !", age);
// On affiche chaine pour vérifier qu'elle contient bien cela :
printf("%s", chaine);
return 0;
}
Code : Console
Tu as 15 ans !
Elle s'utilise de la même manière que printf, mis à part le fait que vous devez lui donner en premier paramètre un pointeur vers la chaîne qui doit recevoir le texte.
Dans mon exemple, j'écris dans chaine "Tu as %d ans", où %d est remplacé par le contenu de la variable age. Toutes les règles du printf s'appliquent, vous pouvez donc si vous le voulez mettre des %s pour insérer d'autres chaînes à l'intérieur de votre chaîne
![smile.png](http://www.siteduzero.com/Templates/images/smilies/smile.png)
Comme d'hab, vérifiez que votre chaîne est suffisamment grande pour accueillir tout le texte que le sprintf va lui envoyer. Sinon, ben... boum
![siffle.png](http://www.siteduzero.com/Templates/images/smilies/siffle.png)