vendredi 10 août 2012

Les Chaîne de Caractères

Qu'est-ce qu'une chaîne de caractères ?


Une chaîne de caractères (appelée string en anglais) est une suite de caractères, c'est-à-dire un ensemble de symboles faisant partie du jeu de caractères, défini par le code ASCII.
En langage C, une chaîne de caractères est un tableau, comportant plusieurs données de type char, dont le dernier élément est le caractère nul '\0', c'est-à-dire le premier caractère du code ASCII (dont la valeur est 0).
Ce caractère est un caractère de contrôle (donc non affichable) qui permet d'indiquer une fin de chaîne de caractères. Ainsi une chaîne composée de n éléments sera en fait un tableau de n+1 éléments de type char.
On peut par exemple représenter la chaîne « Bonjour » de la manière suivante :

B o n j o u r \0

Créer une chaîne de caractères

Pour définir une chaîne de caractères en langage C, il suffit de définir un tableau de caractères. Le nombre maximum de caractères que comportera la chaîne sera égal au nombre d'éléments du tableau moins un (réservé au caractère de fin de chaîne).
char Nom_du_tableau[Nombre_d_elements]
Le nombre d'éléments que comporte le tableau définit la taille maximale de la chaîne, on peut toutefois utiliser partiellement cet espace en insérant le caractère de fin de chaîne à l'emplacement désiré dans le tableau.
Astuce ! En définissant le tableau de la manière suivante, vous mettez en évidence le nombre de caractères maximal de la chaîne :
char Nom_du_tableau[Nombre_d_elements + 1]
Par exemple :   char Chaine[50 + 1] ;
Initialiser une chaîne de caractères
Comme généralement en langage C, il faut initialiser votre chaîne de caractères, c'est-à-dire remplir les cases du tableau avec des caractères, sachant que celui-ci devra obligatoirement contenir le caractère de fin de chaîne '\0'.
Il y a deux façons de procéder :
remplir manuellement le tableau case par case
utiliser les fonctions de manipulation de chaînes fournies dans la librairie standard
Voici un exemple d'initialisation manuelle de chaîne de caractères :

#include <stdio.h>
void main(){
char Chaine[20+1];
Chaine[0]= 'B';
Chaine[1]= 'o';
Chaine[2]= 'n';
Chaine[3]= 'j';
Chaine[4]= 'o';
Chaine[5]= 'u';
Chaine[6]= 'r';
Chaine[7]= '\0';
}
Voici une autre façon (plus simple) d'initialiser une chaîne de caractères :

#include <stdio.h>
void main(){
char Chaine[20+1]={ 'B', 'o', 'n', 'j', 'o', 'u', 'r', '\0' };
}

Les fonctions de manipulation de chaînes de caractères
De nombreuses fonctions de manipulation de chaînes sont directement fournies. Ces fonctions se trouvent dans le fichier d'en-tête <string.h>, c'est la raison pour laquelle il faut ajouter la ligne suivante en début de programme :
#include <string.h>Le fichier <string.h> contient les prototypes de nombreuses fonctions permettant de simplifier l'utilisation et la manipulation de chaînes (environ une quarantaine).
Affichage de la chaîne grâce au %s du printf :  printf("%s", chaine);
Récupération d'une chaîne via un scanf :    scanf("%s", prenom);

B: Manipulations de chaînes de caractères

Les chaînes de caractères étant très souvent employées, et leur format étant strictement défini par la norme C, de nombreuses fonctions permettant de les manipuler sont généralement inclues à aux bibliothèques des compilateurs.
Ainsi, TIGCC et AMS nous fournissent de nombreuses fonctions, dont un bon nombre sont des ROM_CALLs, dédiées au travail avec des chaînes de caractères. Notez que la plupart d'entre elles sont des fonctions ANSI, ce qui garantit que vous les retrouverez avec quasiment tous les compilateurs C existants.
Sous TIGCC, les fonctions de manipulation de chaînes de caractères sont regroupées dans le fichier d'en-tête <string.h>.
Au cours de cette partie, nous allons voir comment copier des chaînes de caractères vers d'autres chaînes de caractères, comment en concaténer, comment en formater, ou encore comment en obtenir la longueur...

1: Longueur d'une chaîne de caractères
Tout d'abord, la fonction strlen permet de déterminer la longueur, en nombre de caractères, de la chaîne de caractères qu'on lui passe en argument. Voici son prototype :
unsigned long strlen(const char *str);
Notez que c'est le nombre de caractères "utiles" qui est retourné : le 0 de fin n'est pas compté.
Par exemple, considérons cette portion de code :
printf("%lu", strlen("salut"));
La valeur affichée sera 5 : la chaîne de caractères "salut" contient 5 caractères, même si elle occupe un sixième espace mémoire pour le 0 de fin de chaîne.

2: Copie de chaînes de caractères

Pour copier une chaîne de caractères vers une autre, il convient d'utiliser la fonction strcpy, qui prend en paramètre un pointeur sur la zone mémoire de destination, et la chaîne d'origine :
char *strcpy(char *destination, const char *origine);
Par exemple :
char str[30];
strcpy(str, "Hello World !");
printf("%s", str);
Cette portion de code affichera "Hello World !".
Notez que la zone de mémoire de destination doit être de taille suffisamment important pour pouvoir contenir la chaîne de caractères que l'on essaye d'y placer, 0 de fin compris. Dans le cas contraire, votre programme risque de corrompre des données, et d'entraîner un plantage.
Cette fonction retourne un pointeur sur la chaîne de destination.

3: Concaténation de chaînes de caractères
A présent, passons à la concaténation de chaînes de caractères.
En informatique, on utilise le terme "concaténer", pour signifier que l'on veut mettre bout à bout deux chaînes de caractères. Par exemple, la concaténation de "Hello " et de "World !" donnera "Hello World !".
C'est la fonction strcat qui remplit ce rôle. Elle accole à la chaîne de caractères passée en second paramètre à la fin de la première.
char *strcat(char *destination, const char *origine);
Par exemple :
char str[30];
strcpy(str, "Hello");
printf("%s", str);
strcat(str, " World !");
printf("%s", str);
Cette portion de code commencera par afficher "Hello", et finira en affichant "Hello World !".
Ici encore, zone de mémoire correspondant à la chaîne de destination doit être de taille suffisamment importante pour pouvoir contenir les textes des deux chaînes de départ, plus le 0 final.
La fonction strcat retourne un pointeur sur la chaîne de destination ; celle qui contiendra le résultat de la concaténation.
Notez que les deux paramètres doivent être des chaînes de caractères valides ! En particulier, le code suivant, où la chaîne de caractères de destination n'a pas été initialisée, ne fonctionnera pas, et risque de causer un plantage :
char str[30];
strcat(str, "Hello World !");
En effet, strcat parcourt la première chaîne jusqu'à trouver son 0 final, puis parcourt la seconde chaîne jusqu'à son 0 final, en ajoutant les caractères de celle-ci à la suite de ceux de la première. Donc, si une des deux chaînes n'a pas de 0 final (autrement dit, si un des paramètres n'est pas une chaîne de caractères !), cela ne fonctionnera pas.

4: Comparaison de chaînes de caractères

Assez souvent, lorsque l'on travaille avec des chaînes de caractères, il nous arrive d'avoir à les comparer, pour savoir laquelle est la plus "grande", la plus "petite", ou si elles sont "égales".
Dans ce but, le C fournit la fonction strcmp, qui prend en paramètres deux chaînes de caractères, et retourne :
0 si les deux chaînes sont égales.
Une valeur supérieure à 0 si la première chaîne est plus "grande" que la seconde.
Une valeur inférieure à 0 si la première chaîne est plus "petite" que la première.
La conversion se faisant sur les codes ASCII de chaque caractères, l'ordre est alphabétique, les majuscules étant plus "petites" que les minuscules.
Voici le prototype de cette fonction :
short strcmp(const unsigned char *str1, const unsigned char *str2);
Par exemple, pour tester si deux chaînes sont égales, nous pourrons utiliser une écriture telle que celle-ci :
if(!strcmp("salut", "salut"))
{
    // Les deux chaînes sont égales
}
Je me permet d'insister sur le fait que la valeur retournée en cas d'égalité entre les deux chaînes de caractères est 0.
Pour la forme, voici un petit exemple ou nous testons les 3 cas : égalité, et plus "petit" ou plus "grand" :
char str1[] = "aaaab";
char str2[] = "aahbag"
short comp = strcmp(str1, str2);
if(!comp)
    printf("str1 == str2");
else if(comp < 0)
    printf("str1 < str2");
else
    printf("str1 > str2");
Si vous êtes curieux, sachez que, en cas de différence entre les deux chaînes, la valeur retournée est égale à la différence entre les codes ASCII du premier caractère différent de chaque chaîne.
Par exemple, si on appelle strcmp sur les chaînes "aaax" et "aazb", la valeur retournée sera 'a'-'z', c'est-à-dire -25 : la chaîne "aaax" est plus petite que la chaîne "aazb".
Si vous avez besoin d'effectuer une comparaison qui ne soit pas sensible à la casse (c'est-à-dire, qui considère que les majuscules et minuscules sont égales), vous pouvez utiliser la fonction suivante :
short cmpstri(const unsigned char *str1, const unsigned char *str2);
Elle fonctionne exactement comme strcmp, sauf qu'elle est un peu plus lente, étant donné qu'elle convertit tous les caractères de majuscule vers minuscule avant d'effectuer la comparaison.

5: Fonctions travaillant uniquement sur les n premiers caractères

La librairie C fourni aussi des fonctions permettant de copier, concaténer, ou comparer des chaînes, mais en se limitant à un certain nombre de caractères, que l'utilisateur peut définir, en comptant à partir du premier de la chaîne.
Ces fonctions sont nommées comme leurs équivalents travaillant sur des chaînes entières, mais en intercalant un 'n' entre "str" et ce que fait la fonction. Il faut aussi leur passer un troisième paramètre, qui correspond au nombre de caractères que la fonction devra traiter.
Voici leurs prototypes :
Pour la copie des n premiers caractères d'une chaîne vers un bloc mémoire :
char *strncpy(char *destination, const char *origine, unsigned long n);
Pour accoler à la fin d'une chaîne les n premiers caractères d'une autre :
char *strncat(char *destination, const char *origine, unsigned long n);
Et enfin, pour comparer les n premiers caractères de deux chaînes :
short strncmp(const unsigned char *str1, const unsigned char *str2, unsigned long n);
Tout comme celles que nous avons vu précédemment, ces fonctions supposent que les chaînes qu'elles doivent lire sont valides (terminées par un 0), et que les zones mémoires où elles doivent écrire sont suffisamment grandes pour contenir ce que l'on essaye d'y placer.
De plus, comme on peut s'y attendre, si le nombre de caractères que vous spécifiez est plus grand que la taille effective de la chaîne, ces fonctions ignoreront le nombre de vous avez spécifié, et s'arrêteront à la fin de la chaîne.
Notez, et c'est important, que, pour strncpy, si le nombre de caractères dans la chaîne d'origine est supérieur ou égal à n, la chaîne de destination ne sera pas terminée par un '\0' ! Dans ce cas, pour que la chaîne de destination soit considèrée comme valide, ce qui est indispensable si vous voulez appeler une autre fonction dessus, il faudra que vous rajoutiez le '\0' de fin de chaîne vous-même !

6: Conversion d'une chaîne de caractères vers un entier ou un flottant

Parfois, on dispose d'une chaîne de caractères, et on sait qu'elle contient une écriture de type numérique. On peut alors être amené à vouloir obtenir ce nombre sous forme d'une variable sur laquelle on puisse faire des calculs, telle, par exemple, un entier ou un flottant.
Il existe donc des fonctions qui permettent de convertir des chaînes de caractères en un type numérique. Les voici :
Pour convertir une chaîne de caractères en entier short :
short atoi(const char *str);
Pour convertir une chaîne de caractères en entier long :
long atol(const char *str);
Pour ces deux fonctions, on passe en paramètre la chaîne de caractères, et on obtient l'entier en retour. L'analyse de la chaîne de caractères s'arrête au premier caractère non valide pour un entier.
Notez que ces fonctions retourneront un résultat indéterminé si vous essayez de les faire travailler sur une valeur plus grande que ce qu'un short (respectivement, un long) peut contenir.
Si vous avez besoin de plus de flexibilité que celle proposée par ces fonctions, je vous conseille de jeter un coup d'oeil sur la documentation de la fonction strtol. Etant donné qu'il est rare que les débutants aient besoin de ce qu'elle permet de faire, je ne la présenterai pas plus ici.
Et, pour convertir une chaîne de caractères en flottant, on utilisera cette fonction :
float atof(const char *str);
Elle s'utilise comme les deux fonctions retournant des entiers.
Si la conversion ne peut se faire, atof renverra la valeur NAN (Not A Number). Vous pourrez vérifier si l'appel a échoué en appelant la fonction is_nan sur la valeur retournée par atof.

7: Formatage de chaînes de caractères
Au cours de ce tutorial, nous avons souvent utilisé la fonction printf, qui permet d'afficher à l'écran du texte, en le formatant : insertion du contenu de variables au cours du texte, nombre de caractères fixes, ...
Le C fourni la fonction sprintf, qui fonctionne exactement de la même façon que printf, à la différence prêt que la chaîne de caractères résultante, au lieu d'être affichée à l'écran, est mémorisée dans une variable.
Voici le prototype de cette fonction :
short sprintf(char *buffer, const char *format, ...);
Le premier paramètre, buffer, correspond à un pointeur vers un tableau de caractères suffisamment grand pour que la fonction puisse y mémoriser la chaîne de caractères formatée.
Le second paramètre, format, correspond à une chaîne de caractères, au sein de laquelle sont utilisés le même type de codes de formatage que pour la fonction printf. Je vous invite à consulter la documentation de printf pour la liste de ces codes.
Ensuite, viennent, dans l'ordre, les paramètres correspondant aux codes de formatage utilisés dans le second paramètre.
Par exemple :
char str[30];
short a = 10;
sprintf(str, "a vaut %d\n", a);
Naturellement, on peut ensuite travailler avec la chaîne de caractères obtenue ; par exemple, pour l'afficher avec une fonction autre que printf.

Aucun commentaire:

Enregistrer un commentaire