sommaire du chapitre :
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
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.
1. Déclaration et mémorisation
Déclaration de chaînes de caractères en langage algorithmique
chaîne
Déclaration de chaînes de caractères en C
char
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.
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"
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.
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]
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é.
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.
6a. Les fonctions de <stdio.h>
Comme nous l'avons déjà vu, la bibliothèque
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
Le retour à la ligne final est remplacé par le symbole de fin de chaîne "\0".
6b. Les fonctions de <string.h>
La bibliothèque
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...
6c. Les fonctions de <stdlib.h>
La bibliothèque <stdlib.h>
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)
6d. Les fonctions de <ctype.h>
Les fonctions de <ctype.h>
Les symboles nationaux (é, è, ä, ü, ß, ç, ...) ne sont pas considérés.
Les fonctions de
Dans la suite,
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(
islower(
isdigit(
isalpha(
isalnum(
isxdigit(
isspace(
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).
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.
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"