En programmation, une chaîne de caractères désigne… du texte, tout simplement ! Et on peut retenir ce texte sous forme de variable en mémoire.
Comme nous l'avons dit plus tôt, notre ordinateur ne peut retenir que des nombres. Les lettres sont exclues. Comment diable les programmeurs font-ils pour manipuler du texte, alors ? Eh bien ils sont malins, vous allez voir !
Utilisez le type char
pour stocker une lettre
Si le type char
permet de stocker des nombres (compris entre -128 et 127), on l'utilise rarement pour ça en C.
En général, même si le nombre est petit, on le stocke dans un int
. Certes, ça prend un peu plus de place en mémoire, mais aujourd'hui, la mémoire, ce n'est vraiment pas ce qui manque sur un ordinateur.
Testons :
int main(int argc, char *argv[])
{
char lettre = 'A';
printf("%d\n", lettre);
return 0;
}
65
On sait donc que la lettre A majuscule est représentée par le nombre 65. B vaut 66, C vaut 67, etc.
Affichez un caractère avec la fonction printf
La fonction printf
peut aussi afficher un caractère via le symbole%c
(c comme caractère) :
int main(int argc, char *argv[])
{
char lettre = 'A';
printf("%c\n", lettre);
return 0;
}
A
Hourra, nous savons afficher une lettre !
On peut aussi demander à l'utilisateur d'entrer une lettre en utilisant le %c
dans un scanf
:
int 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 :
B B
Le premier des deux B est celui que j'ai tapé au clavier, le second est celui affiché par le printf
.
Voyez les chaînes comme des tableaux de type char
Une chaîne de caractères n'est en fait rien d'autre qu'un tableau de type char
.
Si on crée un tableau :
char chaine[5];
et qu'on met :
dans
chaine[0]
la lettre'S'
;dans
chaine[1]
la lettre'a'
,
… on peut ainsi former une chaîne de caractères, c'est-à-dire du texte.
Voici, de manière simplifiée, comment la chaîne est stockée en mémoire :
Ce tableau prend 5 cases en mémoire pour représenter le mot "Salut".
Pourquoi faut-il que la chaîne de caractères se termine 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
, mais de 6 :
Grâce à \0
:
vous n'avez pas à retenir la taille de votre tableau car il indique que le tableau s'arrête à cet endroit ;
vous pouvez passer votre tableau de
char
à une fonction sans avoir à ajouter à côté une variable indiquant la taille du tableau.
Créez et initialisez une chaîne
Si on veut initialiser notre tableau chaine
avec le texte "Salut", on peut utiliser la méthode manuelle mais peu efficace :
char 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 avec un printf
en utilisant le symbole %s
( s
pour string en anglais, qu'on traduit par "chaîne").
Voici le code complet qui crée une chaîne "Salut" en mémoire, et qui l'affiche :
#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 un à un 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 :
Salut
Vous remarquerez que 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 :
int main(int argc, char *argv[])
{
char chaine[] = "Salut"; // La taille du tableau chaine est automatiquement calculée
printf("%s", chaine);
return 0;
}
Salut
À 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 à mettre dans votre tableau, le compilateur C calcule automatiquement la taille nécessaire. C'est-à-dire qu'il compte les lettres et ajoute 1 pour placer le caractère \0
.
Il écrit ensuite, une à une, les lettres du mot "Salut" en mémoire, et ajoute le \0
comme on l'a fait nous-mêmes manuellement quelques instants plus tôt. Bref, c'est bien plus pratique.
Il y a toutefois un défaut : ça ne marche que pour l'initialisation ! Vous ne pouvez pas écrire plus loin dans le code :
chaine = "Salut";
Dans cette vidéo, nous allons voir les différentes méthodes pour créer une chaîne de caractères, en respectant les bonnes pratiques :
Récupérez une chaîne via un scanf
Vous pouvez enregistrer une chaîne entrée par l'utilisateur via un scanf
, via le symbole %s
.
Seul problème : vous ne savez pas combien de caractères l'utilisateur va entrer. 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-Édouard (beaucoup plus de caractères) ?
Pour ça, il n'y a pas 36 solutions. Il va falloir créer un tableau de char
suffisamment grand pour pouvoir stocker le prénom. On va donc créer un char[100]
:
int main(int argc, char *argv[])
{
char prenom[100];
printf("Comment t'appelles-tu ? ");
scanf("%s", prenom);
printf("Salut %s, je suis heureux de te rencontrer !", prenom);
return 0;
}
Comment t'appelles-tu ? Mateo21 Salut Mateo21, je suis heureux de te rencontrer !
Manipulez des chaînes à l'aide de fonctions
Je vais vous présenter les principales :
strlen
pour calculer la longueur d'une chaîne.strcpy
pour copier une chaîne dans une autre.strcat
pour concaténer 2 chaînes.strcmp
pour comparer 2 chaînes.strchr
pour rechercher un caractère.strpbrk
pour rechercher le premier caractère de la liste.strstr
pour rechercher une chaîne dans une autre.sprintf
pour écrire dans une chaîne.
Rajoutez cette ligne en haut des fichiers .c
où vous en avez besoin :
#include <string.h>
1. Calculez la longueur d'une chaîne avec strlen
strlen
(pour "string length") est une fonction qui calcule la longueur d'une chaîne de caractères (sans compter le caractère\0
) :
Vous lui envoyez un seul paramètre (votre chaîne de caractères) ;
Elle vous retourne la longueur de la chaîne.
Maintenant que vous savez ce qu'est un prototype, je vous donne celui de la fonction strlen
:
size_t strlen(const char* chaine);
La fonction prend un paramètre de type const char*
.
Le const
( qui signifie constante) 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
:
int 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;
}
La chaine Salut fait 5 caracteres de long
Pour écrire la fonction strlen
, 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.
Tiens, tout ça m'a donné envie d'écrire moi-même une fonction similaire à strlen
. Ça vous permettra en plus de bien comprendre comment la fonction marche :
int 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 le caractère \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.À chaque passage dans la boucle, on ajoute 1 au nombre de caractères qu'on a analysés.
À 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é !
2. Copiez une chaîne dans une autre avec strcpy
La fonction strcpy
(pour "string copy") permet de copier une chaîne à l'intérieur d'une autre.
Voici son prototype :
char* strcpy(char* copieDeLaChaine, const char* chaineACopier);
Cette fonction prend deux paramètres :
copieDeLaChaine
: c'est un pointeur vers unchar*
(tableau dechar
). C'est dans ce tableau que la chaîne sera copiée.chaineACopier
: c'est un pointeur vers un autre tableau dechar
. Cette chaîne sera copiée danscopieDeLaChaine
.
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.
Testons cela :
int main(int argc, char *argv[])
{
/* On crée une chaîne "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;
}
chaine vaut : Texte copie vaut : Texte
On voit que chaine
vaut "Texte". Jusque-là, 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 chaîne a donc bien été copiée dans copie
.
Schématiquement, la copie a fonctionné comme ceci :
Chaque caractère de chaine
a été placé dans copie
.
3. Concaténez deux chaînes avec strcat
La fonction strcat
(pour "string catenate") ajoute une chaîne à la suite d'une autre. On appelle cela la concaténation.
Supposons que l'on ait les variables suivantes :
chaine1 = "Salut "
chaine2 = "Mateo21"
Si je concatène chaine2
dans chaine1
, alors chaine1
vaudra "Salut Mateo21"
.
Quant à 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 :
char* strcat(char* chaine1, const char* chaine2);
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 : on peut donc ignorer ce que la fonction nous renvoie.
La fonction ajoute à chaine1
le contenu de chaine2
.
Regardons-y de plus près :
int 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;
}
chaine1 vaut : Salut Mateo21 chaine2 vaut toujours : Mateo21
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.
Voici comment fonctionne la concaténation :
Le tableau chaine2
a été ajouté à la suite de chaine1
(qui comprenait une centaine de cases).
Le \0
de chaine1
a été supprimé (en fait, il a été remplacé par le M de Mateo21).
4. Comparez deux chaînes avec strcmp
strcmp
(pour "string compare") compare 2 chaînes entre elles.
Voici son prototype :
int strcmp(const char* chaine1, const char* chaine2);
Les variables chaine1
et chaine2
sont comparées. 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 strcmp
renvoie :
0 si les chaînes sont identiques ;
une autre valeur (positive ou négative) si les chaînes sont différentes.
Voici un code de test :
int main(int argc, char *argv[])
{
char chaine1[] = "Texte de test", chaine2[] = "Texte de test";
if (strcmp(chaine1, chaine2) == 0) // Si chaînes identiques
{
printf("Les chaines sont identiques\n");
}
else
{
printf("Les chaines sont differentes\n");
}
return 0;
}
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.
5. Recherchez un caractère avec strchr
La fonction strchr
recherche un caractère dans une chaîne.
Voici son prototype :
char* 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.
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
:
int 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;
}
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
.
Ce schéma 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".
printf
affiche tous les caractères qu'elle rencontre (d
,e
,
,t
,e
,s
,t
) jusqu'à ce qu'elle tombe sur \0
qui lui dit que la chaîne s'arrête là.
6. Recherchez le premier caractère d'une liste avec strpbrk
Cette fonction 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.
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 y a trouvés. 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'
.
Voici son prototype :
char* strpbrk(const char* chaine, const char* lettresARechercher);
Testons la fonction :
int 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;
}
Voici la fin de la chaine a partir du premier des caracteres trouves : xte de test
7. Recherchez une chaîne dans une autre avec strstr
La fonction strstr
(pour "string string") recherche la première occurrence d'une chaîne dans une autre chaîne.
Son prototype est :
char* strstr(const char* chaine, const char* chaineARechercher);
Le prototype est similaire à strpbrk
, mais attention à ne pas confondre :
strpbrk
recherche UN des caractères ;strstr
recherche toute la chaîne.
Exemple :
int 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 occurrence de test dans Texte de test : %s\n", suiteChaine);
}
return 0;
}
Premiere occurrence 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é.
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 ou non donné quelque chose, et vous afficherez "Le texte que vous recherchiez a été trouvé".
8. Écrivez dans une chaîne avec sprintf
Cette fonction ressemble énormément au printf
sauf qu'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".
C'est une fonction très pratique pour mettre en forme une chaîne. Petit exemple :
#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;
}
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
nn. 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 !
En résumé
Un ordinateur ne sait pas manipuler du texte, il ne connaît que les nombres. Pour régler le problème, on associe à chaque lettre de l'alphabet un nombre correspondant dans une table appelée la table ASCII.
Le type
char
est utilisé pour stocker une et une seule lettre. Il stocke en réalité un nombre, mais ce nombre est automatiquement traduit par l'ordinateur à l'affichage.Pour créer un mot ou une phrase, on doit construire une chaîne de caractères. Pour cela, on utilise un tableau de
char
.Toute chaîne de caractères se termine par un caractère spécial appelé
\0
qui signifie "fin de chaîne".Il existe de nombreuses fonctions toutes prêtes de manipulation des chaînes dans la bibliothèque string. Il faut inclure
string.h
pour pouvoir les utiliser.
Les chaînes de caractères n’ont plus de secret pour vous ! Il est donc temps d’apprendre une nouvelle notion. Passez au chapitre suivant sans tarder, vous allez travailler sur les directives du préprocesseur. Pas d'inquiétude, le prochain chapitre est plus simple que les deux précédents.