Les chaînes de caractères


sommaire du chapitre :

Introduction

1. Déclaration et mémorisation

2. Les chaînes de caractères constantes

3. Initialisation de chaînes de caractères

4. Accès aux éléments d'une chaîne

5. Précédence alphabétique et lexicographique

6. Travailler avec des chaînes de caractères
6a. Les fonctions de <stdio.h>
6b. Les fonctions de <string.h>
6c. Les fonctions de <stdlib.h>
6d. Les fonctions de <ctype.h>

7. Tableaux de chaînes de caractères
7a. Déclaration, initialisation et mémorisation
7b. Accès aux différentes composantes


Introduction

Il n'existe pas de type spécial chaîne ou string en C .
Une chaîne de caractères est traitée comme un tableau à une dimension de caractères (vecteur de caractères).
Il existe quand même des notations particulières et une bonne quantité de fonctions spéciales pour le traitement de tableaux de caractères.

retour au sommaire


1. Déclaration et mémorisation

Déclaration de chaînes de caractères en langage algorithmique

chaîne <NomChaine>

Déclaration de chaînes de caractères en C

char <NomChaine> [<Longueur>] ;

Exemples :
char NOM [20];
char PRENOM [20];
char PHRASE [300];

Espace à réserver

Lors de la déclaration, nous devons indiquer l'espace à réserver en mémoire pour le stockage de la chaîne.
La représentation interne d'une chaîne de caractères est terminée par le symbole "\0" (NULL).
Ainsi, pour un texte de n caractères, nous devons prévoir n+1 octets.

Mémorisation

Comme pour un tableau (étant donné qu'il s'agit bien d'un tableau), le nom d'une chaîne est le représentant de l'adresse du premier caractère de la chaîne.

Remarque :
Pour l'avenir, la ISO (International Organization for Standardization) prévoit un code de caractères multi-octets extensible (UNICODE) qui contiendra tous les caractères et symboles spéciaux utilisés sur toute la terre.
Lors de l'introduction de ce code, les méthodes de mémorisation de la plupart des langages de programmation devront être révisées.

retour au sommaire


2. Les chaînes de caractères constantes

-Les chaînes de caractères constantes (string literals) sont indiquées entre guillemets.
La chaîne de caractères vide est alors: ""

-Dans les chaînes de caractères, nous pouvons utiliser toutes les séquences d'échappement définies comme caractères constants.
Exemple : "Ce \ntexte \nsera réparti sur 3 lignes."

-Le symbole " peut être représenté à l'intérieur d'une liste de caractères par la séquence d'échappement \".

-Le symbole ' peut être représenté à l'intérieur d'une liste de caractères par la séquence d'échappement \'.

-Plusieurs chaînes de caractères constantes qui sont séparées par des signes d'espacement (espaces, tabulateurs ou interlignes) dans le texte du programme seront réunies en une seule chaîne constante lors de la compilation.
Exemple : {"L" , "\'" , "a" , "s" , "t" , "u" , "c" , "e" , "\0"}sera évalué à "L'astuce"

-Plusieurs chaînes de caractères constantes qui sont séparées par des signes d'espacement (espaces, tabulateurs ou interlignes) dans le texte du programme seront réunies en une seule chaîne constante lors de la compilation.
Exemple : "un " "deux" " trois" sera évalué à "un deux trois"

retour au sommaire


3. Initialisation de chaînes de caractères

En général, les tableaux sont initialisés par l'indication de la liste des éléments du tableau entre accolades :
char CHAINE[] = {"H" , "e" , "l" , "l" , "o" , "\0"};

Pour le cas spécial des tableaux de caractères, nous pouvons utiliser une initialisation plus confortable en indiquant simplement une chaîne de caractère constante :
char CHAINE[] = "Hello";

Lors de l'initialisation par [], l'ordinateur réserve automatiquement le nombre d'octets nécessaires pour la chaîne (NombreCaractères+1, ici: 6 octets).
Nous pouvons aussi indiquer explicitement le nombre d'octets à réserver, si celui-ci est supérieur ou égal à la longueur de la chaîne d'initialisation.

retour au sommaire


4. Accès aux éléments d'une chaîne

L'accès à un élément d'une chaîne de caractères peut se faire de la même façon que l'accès à un élément d'un tableau.
En déclarant une chaîne par :
char
A[6];
nous avons défini un tableau A avec six éléments, auxquels on peut accéder par:
A[0], A[1], ... , A[5]

retour au sommaire


5. Précédence alphabétique et lexicographique

Précédence alphabétique des caractères

La précédence des caractères dans l'alphabet d'une machine est dépendante du code de caractères utilisé.
Pour le code ASCII, nous pouvons constater l'ordre suivant :
. . . ,0,1,2, ... ,9, . . . ,A,B,C, ... ,Z, . . . ,a,b,c, ... ,z, . . .

Remarque : Les symboles spéciaux (' ,+ ,- ,/ ,{ ,] , ...) et les lettres accentuées (é ,è ,à ,û , ...) se trouvent répartis autour des trois grands groupes de caractères (chiffres, majuscules, minuscules) ; leur précédence ne correspond à aucune règle d'ordre spécifique.

Relation de précédence

De la précédence alphabétique des caractères, on peut déduire une relation de précédence "est inférieur à" sur l'ensemble des caractères.
Ainsi, on peut dire que :
"0" est inférieur à "Z"
et noter :
"0" < "Z"
car dans l'alphabet de la machine, le code du caractère "0" (ASCII: 48) est inférieur au code du caractère "Z" (ASCII: 90).

Précédence lexicographique des chaînes de caractères

En nous basant sur cette relation de précédence alphabétique des caractères, nous pouvons définir une précédence lexicographique pour les chaînes de caractères.
Cette relation de précédence suit l'ordre du dictionnaire et est définie de façon récurrente :
-La chaîne vide "" précède lexicographiquement toutes les autres chaînes.
-La chaîne A = "a1a2a...ap" (p caractères) précède lexicographiquement la chaîne B = "b1b2...bm" (m caractères)
si "a1" < "b1"
OU
si "a1" = "b1" ET "a2a3...ap" < "b2b3...bm"

Exemples :

"ABC" précède "BCD" car "A"<"B"
"ABC" précède "B" car "A"<"B"
"Abc" précède "abc" car "A"<"a"

Remarque : malheureusement, il existe différents codes de caractères (ASCII, EBCDIC, ISO...) et l'ordre lexicographique est dépendant de la machine, même la fonction strcmp qui indique la précédence lexicographique de deux chaînes de caractères dépend du code de caractères utilisé.

retour au sommaire


6. Travailler avec des chaînes de caractères

Les bibliothèques de fonctions de C contiennent une série de fonctions spéciales pour le traitement de chaînes de caractères.
Sauf indication contraire, les fonctions décrites dans ce chapitre sont portables conformément au standard ANSI-C.

retour au sommaire

6a. Les fonctions de <stdio.h>

Comme nous l'avons déjà vu, la bibliothèque <stdio.h> nous offre des fonctions qui effectuent l'entrée et la sortie des données.
A côté des fonctions printf et scanf que nous connaissons déjà, nous y trouvons les deux fonctions puts et gets, spécialement conçues pour l'écriture et la lecture de chaînes de caractères.

Affichage de chaînes de caractères

printf avec le spécificateur de format %s permet d'intégrer une chaîne de caractères dans une phrase.
En plus, le spécificateur %s permet l'indication de la largeur minimale du champ d'affichage.
Dans ce champ, les données sont justifiées à droite.
Si on indique une largeur minimale négative, la chaîne sera justifiée à gauche.
Un nombre suivant un point indique la largeur maximale pour l'affichage.

Exemples :
char NOM[] = "hello, world";
printf(":%s:", NOM);
renvoit :hello, world:
printf(":%5s:", NOM);
renvoit :hello, world:
printf(":%15s:", NOM);
renvoit : hello, world:
printf(":%-15s:", NOM);
renvoit :hello, world :
printf(":%.5s:", NOM);
renvoit :hello:

puts est idéale pour écrire une chaîne constante ou le contenu d'une variable dans une ligne isolée.
Syntaxe : puts(<Chaine>)
Effet: puts écrit la chaîne de caractères désignée par <Chaine> sur stdout et provoque un retour à la ligne.
En pratique, puts(TXT); est équivalent à printf("%s \n",TXT);

Lecture de chaînes de caractères

scanf avec le spécificateur %s permet de lire un mot isolé à l'intérieur d'une suite de données du même ou d'un autre type.
Cette fonction lit alors un mot du fichier d'entrée standard stdin et le mémorise à l'adresse qui est associée à %s.

Exemple :
char LIEU[25];
int JOUR, MOIS, ANNEE;
printf("Entrez lieu et date de naissance : \n");
scanf("%s %d %d %d", LIEU, &JOUR, &MOIS, &ANNEE);

gets est idéal pour lire une ou plusieurs lignes de texte (p.ex. des phrases) terminées par un retour à la ligne.
Syntaxe: gets(<Chaine>)
Effet: gets lit une ligne de caractères de stdin et la copie à l'adresse indiquée par <Chaine>.
Le retour à la ligne final est remplacé par le symbole de fin de chaîne "\0".

retour au sommaire

6b. Les fonctions de <string.h>

La bibliothèque <string.h> fournit une multitude de fonctions pratiques pour le traitement de chaînes de caractères.
Voici une brève description des fonctions les plus fréquemment utilisées :

strlen(<Chaine>) renvoit la longueur de <Chaine> sans compter le "\0" final
strcpy(<Chaine1> , <Chaine2>) copie <Chaine1> dans <Chaine2>
strcat(<Chaine1> , <Chaine2>) ajoute <Chaine2> à la fin de <Chaine1>
strcmp(<Chaine1>,<Chaine2>) compare <Chaine1> et <Chaine2> lexicographiquement et renvoit :
négatif si <Chaine1> < <Chaine2>
0 si <Chaine1> = <Chaine2>
positif si <Chaine1> > <Chaine2>
strncpy(<Chaine1>,<Chaine2>,<EntierPositifN>) copie au plus <EntierPositifN> caractères de <Chaine2> dans <Chaine1>
strncat(<Chaine1>,<Chaine2>,<EntierPositifN>) copie au plus <EntierPositifN> caractères de <Chaine2> à la din de <Chaine1>

Beaucoup d'autres fonctions très intéressantes sont implémentées dans <string.h>, je vous conseille de vous reporter directement à la définition de cette classe afin d'en savoir plus...

retour au sommaire

6c. Les fonctions de <stdlib.h>

La bibliothèque <stdlib.h> contient des déclarations de fonctions pour la conversion de nombres en chaînes de caractères et vice-versa.

Conversion de chaîne de caractères en nombre

atoi(<Chaine>) renvoit la valeur numérique de <Chaine comme int
atol(<Chaine>) renvoit la valeur numérique de <Chaine comme long
atod(<Chaine>) renvoit la valeur numérique de <Chaine comme double

Règles générales de conversion :

Les espaces au début d'une chaîne sont ignorés
Il n'y a pas de contrôle du domaine de la cible
La conversion s'arrête au premier caractère non convertible
Pour une chaîne non convertible, les fonctions retournent zéro

Conversion de nombre en chaine de caractères

Le standard ANSI-C ne contient pas de fonctions pour convertir des nombres en chaînes de caractères.
Si on se limite aux systèmes fonctionnant sous DOS, on peut quand même utiliser les fonctions itoa, ltoa et ultoa qui convertissent des entiers en chaînes de caractères.

itoa(<NombreINT> , <Chaine> , <BaseConversion>)
ltoa(<NombreINT> , <Chaine> , <BaseConversion>)
ultoa(<NombreINT> , <Chaine> , <BaseConversion>)

La conversion est faite dans la base <BaseConversion> (2 ... 36)

retour au sommaire

6d. Les fonctions de <ctype.h>

Les fonctions de <ctype.h> servent à classifier et à convertir des caractères.
Les symboles nationaux (é, è, ä, ü, ß, ç, ...) ne sont pas considérés.
Les fonctions de sont indépendantes du code de caractères de la machine et favorisent la portabilité des programmes.
Dans la suite, représente une valeur du type int qui peut être représentée comme caractère.

Fonctions de classification et de conversion

Les fonctions de classification suivantes fournissent un résultat du type int différent de zéro, si la condition respective est remplie, sinon zéro.

isupper(<Chaine>) si <Chaine> est une majuscule ('A'...'Z')
islower(<Chaine>) si <Chaine> est une minuscule ('a'...'z')
isdigit(<Chaine>) si <Chaine> est un chiffre décimal ('0'...'9')
isalpha(<Chaine>) si islower(<Chaine>) ou isupper(<Chaine>)
isalnum(<Chaine>) si isalpha(<Chaine>) ou isdigit(<Chaine>)
isxdigit(<Chaine>) si est un chiffre hexadécimal ("0"..."9" ou "A"..."F" ou "a"..."f")
isspace(<Chaine>) si est un signe d'espacement (" ", "\t", "\n", "\r", "\f" )

retour au sommaire


7. Tableaux de chaînes de caractères

Souvent, il est nécessaire de mémoriser une suite de mots ou de phrases dans des variables.
Il est alors pratique de créer un tableau de chaînes de caractères, ce qui allégera les déclarations des variables et simplifiera l'accès aux différents mots (ou phrases).

retour au sommaire

7a. Déclaration, initialisation et mémorisation

Un tableau de chaînes de caractères correspond à un tableau à deux dimensions du type char, où chaque ligne contient une chaîne de caractères.

Déclaration

char <NomTableau> [NombreChaine] [DimensionChaine] ;

Initialisation

Lors de la déclaration il est possible d'initialiser toutes les composantes du tableau par des chaînes de caractères constantes :
char JOUR[7][9]=
{
"lundi",
"mardi",
"mercredi",
"jeudi",
"vendredi",
"samedi",
"dimanche"};

Mémorisation

Les tableaux de chaînes sont mémorisés ligne par ligne.
La variable JOUR de l'exemple précédent aura donc besoin de 7*9*sizeof(char) = 63 octets en mémoire.

retour au sommaire

7b. Accès aux différentes composantes

Il est possible d'accéder aux différentes chaînes de caractères d'un tableau, en indiquant simplement la ligne correspondante.

Exemple :
L'exécution des trois instructions suivantes :
char JOUR[7][9]= {"lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"};
int I = 2;
printf("Aujourd'hui, c'est %s !\n", JOUR[I]);
affichera la phrase:
Aujourd'hui, c'est mercredi !

Affectation

Des expressions comme JOUR[I] représentent l'adresse du premier élément d'une chaîne de caractères.
N'essayez donc pas de "modifier" une telle adresse par une affectation directe !
L'attribution d'une chaîne de caractères à une composante d'un tableau de chaînes se fait en général à l'aide de la fonction strcpy.

Exemple : strcpy(JOUR[3], "Jeudi");

Accès aux caractères

Evidemment, il existe toujours la possibilité d'accéder directement aux différents caractères qui composent les mots du tableau.
Pour cela, il suffit de lancer une instruction du type :
char JOUR[7][9]= {"lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"};
char LETTRE;
LETTRE = JOUR [4][1]
on obtient LETTRE = "V"

retour au sommaire
chapitre suivant