m5_chaines de caractères

19
_ Algorithmique / langage C _ Module 5 - Chaines de caractères 1 Les trois aspects d'une chaine rencontrés en C ......................... 3 1.1 Définition chaine de caractères .............................................. 3 1.2 Une constante chaîne de caractères ................................... 3 1.3 Un tableau de caractères avec ‘\0’ final ................................... 3 1.4 Un pointeur char* ................................................................... 4 1.4.1 Base pointeur ............................................................................................. 4 1.4.2 Utilisation des opérateurs crochet [ ] ....................................................... 4 1.4.3 Attention à la validité d'une adresse mémoire .......................................... 5 1.4.4 Tableau de char*, liste de chaines ...................................................... 6 M5.1 Exercices : bogue typique, liste de chaines, adresses ............................. 7 2 Saisie et affichage standard (mode console) ......................... 9 2.1 Trois fichiers cachés d’entrées-sorties .................................... 9 2.2 Saisir une chaîne .................................................................... 9 2.2.1 Fonction getchar() et fgetc() .................................................................... 9 2.2.2 Fonction scanf(), fscanf() .................................................................... 11 2.2.3 Fonction fgets() ................................................................................. 11 2.3 Afficher une chaîne .................................................................... 12 2.3.3 Fonction puts() et fputs() .................................................................... 12 2.3.2 Fonction fprintf() .................................................................... 12 M5.2 Exercices : saisie et affichages .................................................................... 12 3 Opérations de base sur les chaînes .............................................. 15 3.1 Modifier ......................................................................................... 15 3.2 Récupérer la longueur .................................................................... 16 3.3 Copier ......................................................................................... 17 3.4 Concaténer .............................................................................. 17 3.5 Comparer ......................................................................................... 17 M5.3 Exercices : manipulations sur les chaînes ........................................... 18 1

Upload: ahmad-elhamri

Post on 12-Dec-2015

213 views

Category:

Documents


0 download

DESCRIPTION

une fichier utile pour la luanguage c info2

TRANSCRIPT

Page 1: M5_chaines de Caractères

_ Algorithmique / langage C _Module 5 - Chaines de caractères

1 Les trois aspects d'une chaine rencontrés en C ......................... 31.1 Définition chaine de caractères .............................................. 31.2 Une constante chaîne de caractères ................................... 31.3 Un tableau de caractères avec ‘\0’ final ................................... 31.4 Un pointeur char* ................................................................... 4

1.4.1 Base pointeur ............................................................................................. 41.4.2 Utilisation des opérateurs crochet [ ] ....................................................... 41.4.3 Attention à la validité d'une adresse mémoire .......................................... 51.4.4 Tableau de char*, liste de chaines ...................................................... 6M5.1 Exercices : bogue typique, liste de chaines, adresses ............................. 7

2 Saisie et affichage standard (mode console) ......................... 92.1 Trois fichiers cachés d’entrées-sorties .................................... 92.2 Saisir une chaîne .................................................................... 9

2.2.1 Fonction getchar() et fgetc() .................................................................... 92.2.2 Fonction scanf(), fscanf() .................................................................... 112.2.3 Fonction fgets() ................................................................................. 11

2.3 Afficher une chaîne .................................................................... 122.3.3 Fonction puts() et fputs() .................................................................... 122.3.2 Fonction fprintf() .................................................................... 12M5.2 Exercices : saisie et affichages .................................................................... 12

3 Opérations de base sur les chaînes .............................................. 153.1 Modifier ......................................................................................... 153.2 Récupérer la longueur .................................................................... 163.3 Copier ......................................................................................... 173.4 Concaténer .............................................................................. 173.5 Comparer ......................................................................................... 17

M5.3 Exercices : manipulations sur les chaînes ........................................... 18

1

Page 2: M5_chaines de Caractères

2

Page 3: M5_chaines de Caractères

1 Les trois aspects d'une chaine rencontrés en C

Le principe de la chaîne de caractères est présenté également dans le module sur les tableaux et de nombreux exercices de manipulation de chaines via des tableaux y sont proposés. L'objectif est ici de rassembler tout ce qui concerne les chaines de caractères et d'y ajouter quelques éléments importants, notamment la représentation pointeur, char*, de la chaine. Les trois premiers points, définition, constante, tableau ont déjà été présenté ainsi que les fonctions scanf(), fgets() et fprintf(). Les autres points sont nouveaux.

1.1 Définition chaine de caractères

Dans le langage C une lettre, un caractère, sont codés sur un octet et correspondent au type "char". Une constante de type caractère apparaît entourée par deux apostrophes. ' a ' est la constante caractère a, c’est la lettre a dans un programme. Pour obtenir des mots il faut assembler des caractères, d’où la construction d’une "chaîne de caractères".

La chaîne de caractères est une suite de caractères terminée par le caractère nul : ' \0 '. Ce caractère vaut zéro. La suite est délimitée par des guillemets, par exemple "bonjour" est une chaîne de caractères. En fait cette suite de caractères correspond à un tableau de huit caractères, sept lettres plus le caractère nul '\0' qui signale la fin de la chaîne. C’est un tableau de char. L’espace, qui est une ponctuation, est aussi un caractère. De ce fait une chaîne de caractère peut contenir une phrase entière ou plusieurs. "Il fait beau. Je prends ma canne et mon chapeau." est une chaîne de caractères. Le principe est toujours le même mais il y a trois formes sous lesquelles se présentent les chaînes de caractères dans un programme.

1.2 Une constante chaîne de caractères

"bonjour" dans un programme est une constante chaîne de caractères. En mémoire c’est un tableau de caractères. Il contient les caractères de la chaîne et se termine par un ' \0 ' qui en marque la fin mais sous cette forme il n’est pas possible de modifier ses éléments, tout simplement parce qu'il n'y a pas moyen d'y accéder. Par exemple :

printf ("bonjour");

1.3 Tableau de caractères avec ‘\0’ final

Si elle a besoin d’être manipulée la chaîne est un tableau ordinaire de caractères terminé par '\0' :

char chaine1[10]={'b', 'o', 'n', 'j', 'o', 'u', 'r', '\0'};

ou encore

char chaine2[]="bonjour";

3

Page 4: M5_chaines de Caractères

A propos de l’initialisation des deux exemples ci-dessus, "chaine1[10]" a deux cases disponibles en plus (initialisées à zéro) et la taille du tableau "chaine2" est automatiquement ajustée sur le nombre de caractères de la chaîne qui lui est affectée à l’initialisation. Le ' \0 ' final en fait implicitement partie. La taille du tableau "chaine2" est alors de huit caractères. Sous cette forme il est possible d’accéder à chaque élément de la chaîne et de le modifier :

chaine1[0]='B';chaine1[3]='s';chaine1[5]='i';

Après ces modifications le tableau chaine1 contient "Bonsoir"On peut bien sur modifier tous les éléments de la chaîne via une boucle, par exemple :

int i;for (i=0; chaine2[i]!= '\0'; i++)

chaine2[i]++;

A l’issue de la boucle tous les éléments de chaine2 ont augmenté de 1, c'est-à-dire que 'a' est devenu 'b', 'b' est devenu 'c', 'c' est devenu 'd' etc. chaine2 contient maintenant la chaîne "cpokpvs".

1.4 Pointeur char*

1.4.1 Base pointeur

Une chaîne de caractères peut également apparaître dans un programme sous la forme d’un pointeur de caractères, c'est à dire un char* :

char* ch="bonjour";

Un pointeur est une variable qui prend comme valeur des adresses mémoire. Les pointeurs sont évoqués dans le section sur les tableaux en paramètre de fonction du module fonction et un module complet porte sur les pointeurs.

ch est ici un pointeur de type pointeur de caractères, un char*. L’adresse mémoire de la constante chaîne de caractères "bonjour" lui est affectée. Cette adresse est en fait l’adresse du premier élément de cette chaîne. En effet, une chaine de caractères est un tableau et un tableau correspond toujours à l’adresse du premier élément. Il suffit d’affecter cette adresse à un pointeur pour pouvoir manipuler le tableau à partir du pointeur, c'est à dire à partir de son adresse mémoire. Le pointeur ch ci-dessus contient l’adresse de la chaîne "bonjour" qui se termine par le caractère nul ' \0 '.

1.4.2 Utilisation de l'opérateur crochet [ ]

L'utilisation de l'opérateur crochet [ ] est possible ensuite exactement comme avec un tableau statique :

char* ch="bonjour";ch[0]='B';ch[3]='s';ch[5]='i';// Après ces modifications la chaine ch contient "Bonsoir".

4

Page 5: M5_chaines de Caractères

1.4.3 Attention à la validité d'une adresse mémoire

Lorsqu'un tableau statique est déclaré dans un programme, l'espace mémoire requis est automatiquement réservé par le compilateur au moment de la compilation. C'est pourquoi il est possible d'écrire dans cet espace et d'utiliser le tableau. En revanche ce n'est pas le cas avec un pointeur. Lorsqu'un pointeur est déclaré dans le programme il ne contient pas l'adresse mémoire d'un bloc réservé, il contient n'importe quoi, une adresse aléatoire, ce qui traîne dans la mémoire et si l'on tente d'écrire à une adresse mémoire dans un bloc non réservé le programme plante ou quitte brutalement avec un message d'erreur. Par exemple :

int main(){char*ptr;char tab[80];

printf("entrer une phrase :\n");fgets(tab,80,stdin);printf("tab : %s\n",tab);

printf("entrer une autre phrase :\n");fgets(ptr,80,stdin); // ERREUR !! le programme quitteprintf("ptr : %s\n",ptr);

return 0;}

En effet le pointeur ptr ne contient pas d'adresse valide, accessible en écriture.En revanche si l'on affecte à ptr l'adresse du tableau tab, ça marche :

int main(){char*ptr;char tab[80];

printf("entrer une phrase :\n");fgets(tab,80,stdin);printf("tab : %s\n",tab);

ptr=tab;printf("entrer une autre phrase :\n");fgets(ptr,80,stdin); // okprintf("ptr : %s",ptr); //printf("tab : %s\n",tab); // ptr et tab sont identiques

return 0;}

Si ptr prend l'adresse de tab écrire à partir de ptr revient à écrire à partir de tab puisque c'est à la même adresse en mémoire, c'est à dire au même endroit dans la mémoire. Attention donc parce que dans ce cas ptr et tab sont deux accès pour le même bloc de mémoire et non deux blocs différents.

En fait, l'intérêt essentiel du pointeur par rapport au tableau statique, que ce soit pour des chaines de caractères ou non, est la possibilité d'allouer dynamiquement des zones de mémoire. C'est à dire la possibilité de réserver à la demande, pendant l'exécution du programme, le nombre exacte d'octets nécessaires pour le stockage des données. Cette technique est abordée dans le module pointeur.

5

Page 6: M5_chaines de Caractères

1.4.4 Tableau de char*, liste de chaines

En ce qui concerne les chaines de caractères, les pointeurs char* sont souvent présents en paramètre de fonction. En effet les formes char*s, char s[ ] et même avec une taille spécifiée char s[80] sont équivalentes en paramètre de fonction.

Mais un intérêt du pointeur pour les chaines de caractères maintenant est de pouvoir constituer des ensembles de chaînes de caractères plus facilement. Une liste de mots devient un tableau de pointeurs de caractères. Par exemple :

char* liste_mots[]={"titi", "totofait du vélo", "tutu", "tata go to the sea", "fin" };

Avec une matrice de char il faut écrire :

char mat_mots[][100]={"titi", "totofait du vélo", "tutu", "tata go to the sea", "fin" };

Et ce n'est pas la même chose en mémoire. La matrice de char est moins souple enmémoire. Dans le cas du tableau de pointeurs de caractères la taille mémoire est exactement celle du nombre des caractères. Dans celui de la matrice de caractère, qui est un tableau de tableaux de caractères, on a un bloc mémoire de 5*100 octets réservé quelque soit la taille des mots et il ne faut pas qu'un mot ou la phrase dépasse 100 caractères.

Lorsque la taille du tableau de char* n’est pas explicite, par exemple en cas de liste très longue de mots ou de phrases, le problème est de connaître la fin du tableau. Pour liste_mots et mat_mots le mot "fin" indique qu’il s’agit du dernier mot dans le tableau et les deux peuvent être parcourus de la façon suivante :

int i;for (i=0; strcmp("fin", liste_mots[i]) != 0 ; i++)

printf(“%s\n”,liste_mots[i]);

La fonction strcmp() compare deux chaînes de caractères et renvoie une valeur négative, nulle ou positive selon que la première est inférieure, égale ou postérieure dans l’ordre lexicographique.

Dans notre exemple la boucle va continuer jusqu’à arriver à l’indice de la chaîne "fin" (l’indice i est égal à 4) là la fonction strcmp() renvoie 0, le test devient faux et la boucle s’arrête.

Une autre méthode consiste à utiliser l’adresse 0 de la mémoire. Cette adresse est réservée comme adresse dite NULL et la norme du langage prescrit qu’elle ne soit jamais utilisée. La formule suivante permet d’obtenir une sentinelle à NULL dans un tableau de char* :

((char*)0)

En fait il s’agit d'un cast c'est à dire d’une conversion de type. La valeur 0, de type int, est castée en char*, c'est-à-dire qu’elle change de type pour devenir une valeur de type char*, à savoir l’adresse mémoire dite NULL jamais utilisée par un objet. Notre liste de mots peut s’écrire de la façon suivante :

6

Page 7: M5_chaines de Caractères

char* liste_mots[ ] ={ "titi", "toto fait du vélo", "tutu", "tata go to the sea", ((char*)0) };

et le test de la boucle peut devenir :

int i;for (i=0; liste_mots[i] != NULL ; i++)

printf(“%s\n”,liste_mots[ i ]);

M5.1 Exercices : bogue typique, liste de chaines, adresses

Exercice 1Quels résultats fournit ce programme ?

#include <stdio.h>int main(){char*s="bonjour";int i;

for (i=0; i<3; i++)putchar(s[i]);

putchar('\n');i=0;while(s[i])

putchar(s[i++]);return 0;

}

Exercice 2Écrire un programme qui demande à l'utilisateur de lui fournir un nombre entier entre 1 et 7 et qui affiche le nom du jour de la semaine correspondant (1 : lundi, 2 : mardi etc.)

Exercice 3Que fait le programme suivant ?, Y a t-il des erreurs, si oui lesquelles ? comment les corriger ? :

int main(){char*s1;char s2[80];int i;

fgets(s2,100,stdin);strcpy(s1, s2);

s1=s2;fgets(s2,100,stdin);if (strcmp(s1,s2)==0)

printf("les deux phrase sont identiques\n");else

printf("elles sont différentes\n");

s1="bonjour";printf("s1 :%s\n",s1);strcpy(s2,"il fait beau je prends ma canne et mon chapeau");printf("s2 :%s\n",s2);

7

Page 8: M5_chaines de Caractères

while(s2[i]){ s1[i]=s2[i];

i++;}printf("s1 :%s\n",s1);printf("s2 :%s\n",s2);return 0;

}

Exercice 4Créer un jeu de 52 cartes à partir d'une liste de mots. Au départ, affichez le jeu ordonné par couleurs. Ensuite, faire une fonction de mélange des cartes, faire une fonction de distribution des cartes entre deux joueurs et afficher le jeu de chacun.

Exercice 5soit une liste de mot :char*liste[ ]={"moule","frite","patate","pomme","camembert","gruyère",crêpes", "miel", "cidre","omelette","fin"};Faire un programme qui affiche la liste telle quelle, puis la liste classée en ordre alphabétique. Le classement par ordre alphabétique est fait dans une fonction qui reçoit la liste en argument.

8

Page 9: M5_chaines de Caractères

2 Saisie et affichage standard (mode console)

2.1 Trois fichiers cachés d’entrées-sorties

Quand un programme C est lancé, l’environnement du système d’exploitation est chargé d’ouvrir trois fichiers et de fournir les pointeurs associés à ces fichiers. Ces fichiers sont l’entrée standard avec le pointeur correspondant stdin, la sortie standard avec le pointeur stdout et l’erreur standard avec le pointeur stderr. stdout et stderr sont reliés à l’écran. stdin est relié au clavier.

Ainsi en mode texte standard toutes les entrées se font via une écriture dans le fichier stdin. Les sorties, à savoir un affichage texte console, se font avec une écriture dans le fichier stdout. stderr double stdout et permet un affichage à l’écran dévolu à la gestion des erreurs.

2.2 Saisir une chaîne

2.2.1 Fonction getchar(), fgetc() et getc()

Ces trois fonctions permettent d'entrer une chaine caractère par caractère. Toutes les lettres entrées sont empilée dans le fichier d'entrée et la pile de lettres peut être dépilée ensuite, lettre par lettre.

int getchar(void) ------- <stdio.h>Cette fonction retourne un caractère lu sur l'entrée standard, c'est à dire sur le fichier stdin. Elle retourne la valeur EOF en cas de fin de fichier ou d'erreur (détail dans le module sur les fichiers).Lorsque la fonction est appelée, elle attend l'entrée utilisateur et cette entrée prend fin lorsque l'utilisateur tape enter. Toutes les lettres entrées par l'utilisateur sont empilées dans le buffer d'entrée stdin et lorsque l'utilisateur tape enter le buffer est dépilé. Par exemple :

int main(){int c;

c=getchar();printf("%c\n",c);return 0;

} Lorsque ce programme est lancé, dans la fenêtre console le curseur en écriture clignote, une entrée clavier est attendue attendue. Vous pouvez entrer plusieurs lettres par exemple azertyuiopp, l'entrée s'arrête quand enter, c'est à dire le caractère '\n', est tapé. A ce moment uniquement le retour de la fonction est effectué. Elle renvoie la première lettre entrée. Pour récupérer toutes les lettres entrées il faut utiliser une boucle de la façon suivante :

int main(){ int c=0; while ( c!='\n'){ c=getchar();

9

Page 10: M5_chaines de Caractères

printf("%c--",c); } return 0;}

Lorsque ce programme est lancé, c vaut 0, c'est différent de '\n' donc on rentre dans la boucle. la fonction getchar() empile les entrées, par exemple "azerty" jusqu'à ce que enter y mette fin. Dés que l'utilisateur tape enter, la variable c prend successivement les valeurs entrées. D'abord la valeur 'a', printf() est exécuté et a-- s'affiche dans la fenêtre console. Ensuite le test est effectué, c différent de '\n' alors le dépilement continue. c prend la valeur 'z', printf() est exécuté et z-- s'affiche à la suite dans la fenêtre console, le test est effectué, 'z' différent de '\n' , c prend la valeur 'e', e-- est affiché à la suite etc. Lorsque c prend la valeur '\n', printf() est appelé, il y a un retour chariot et --est affiché sur la ligne suivante, le test est effectué et la boucle prend fin. Le résultat est donc :a--z--e--r--t--y----

Si vous placez l'appel de getchar() directement dans le test de la boucle, ce qui change c'est que le test a lieu avant l'affichage. Ainsi lorsque c vaut '\n' l'affichage n'a pas lieu :

int main(){ int c; while ( (c=getchar())!='\n') printf("%c--",c); return 0;}

Le résultat est :a--z--e--r--t--y--

Pour éviter de conserver la pile en mémoire il faut appelé en plus la fonction rewind() :

int main(){ int c; while ( (c=getchar())!='\n'){ printf("%c--",c); rewind(stdin); // réinitialisation du fichier d'entrée stdin } return 0;}

Quelque soit la pile des lettres entrées, à chaque fois la première lettre est affichée et le reste de la pile n'est plus pris en compte.

int fgetc(FILE*) ------- <stdio.h>Cette fonction retourne un caractère lu sur sur le fichier spécifié en paramètre. Elle retourne EOF en cas de détection de fin de fichier ou d'erreur. Un appel de fgetc() avec stdin comme fichier spécifié, fgetc(stdin), est équivalent à getchar().

int getc(FILE*) ------- <stdio.h>Équivalent sous forme de macro à fgetc(). Il est conseillé d'utiliser plutôt fgetc().

10

Page 11: M5_chaines de Caractères

2.2.2 Fonction scanf(), fscanf()

Nous allons nous concentrer ici sur l'utilisation de scanf() pour récupérer des chaines de caractères entrées par un utilisateur.

int scanf (const char*, …) ------- <stdio.h>La fonction scanf() avec le spécificateur %s lit une chaîne sur le fichier d’entrée standart stdin jusqu’au premier espace ou retour chariot rencontré. Elle recopie alors le mot à l’adresse spécifiée. Cette chaîne réceptrice doit être assez grande et disposer d’assez de mémoire pour pouvoir recevoir la chaîne qui est entrée sous peine d’un débordement. La fonction scanf permet de récupérer un texte mot après mot en éliminant tous les espaces. Par exemple le programme suivant entre successivement quatre mots et les affiche :

int main(int argc, char *argv[]){char buf[100];int i;

for (i=0; i<4; i++){ printf("entrer la chaine %d :\n",i+1); scanf("%s",buf); printf("chaine %d : %s\n",i+1,buf); } return 0;}

Elle retourne le nombre de bonne réponse obtenue compte tenu des spécifications demandées et des entrées effective de l’utilisateur. Comme pour la fonction getchar() ci-dessus l'entrée utilisateur est empilée dans un buffer, le fichier stdin et dépilé ensuite. Dans l'exemple ci-dessus si l'utilisateur entre au départ : "tata fait du vélo le dimanche matin" le programme sort :

entrer la chaine 1 :tata fait du vélo le dimanche matinchaine 1 : tataentrer la chaine 2 :chaine 2 : faitentrer la chaine 3 :chaine 3 : duentrer la chaine 4 :chaine 4 : vélo

int fscanf(FILE*, const char*, ...) ------- <stdio.h>Cette fonction est équivalente à scanf() sauf qu'elle permet de lire des données sur n'importe quel fichier spécifié en p1. Dans l'exemple précédent,

fscanf(stdin,"%s",buf); est équivalent à scanf("%s",buf);

2.2.3 Fonction fgets()

char* fgets (char*, int, FILE*) ------- <stdio.h>Cette fonction lit une chaîne entrée sur le fichier spécifié au paramètre p3 (dans le cas de l’entrée standard ce fichier sera stdin) jusqu’à un ‘\n’ ou jusqu’à ce que p2-1 caractères aient été lus, le ‘\n’ final compris. Tous les caractères lus sont placés à partir de l’adresse spécifiée

11

Page 12: M5_chaines de Caractères

au paramètre p1. Un \0 est ajouté comme dernier caractère après le \n.

int main(int argc, char *argv[]){char buf[100]; printf("enter une chaine :\n");

fgets(buf,100,stdin); puts(buf); // équivalent à printf(“%s\n”,buf); fputs(buf,stdout);// équivalent à printf(“%s”,buf); (sans ajout de \n) return 0;}

2.3 Afficher une chaîne

2.3.2 Fonction fputs() et puts()

int fputs(char*, FILE*) ------- <stdio.h>Cette fonction permet d’écrire (copier) la chane passée au paramètre p1 le fichier passé au paramètre p2, stdout s’il s’agit de la sortie standard. Elle retourne EOF (indicateur de fin de fichier, voir section suivante) si une erreur se produit.

int puts (char*) ------- <stdio.h>Cette fonction est équivalente à la précédente mais elle copie la chaine passée sur le fichier de sortie standard sans qu’il ait besoin d’être spécifié et d’autre part elle ajoute un \n à la suite de la chaîne ce qui dispose le curseur en écriture sur la ligne suivante. Pour cette raison un appel à fputs() avec stdout comme destination en écriture est différent de puts()

2.3.1 Fonction printf(), fprintf()

int printf (const char*, ...) ------- <stdio.h>Cette fonction bien connue maintenant permet d’afficher sur la sortie standard une chaîne de caractère via le format %s. C'est un appel déguisé de la fonction fprintf() ci-dessous.

int fprintf (FILE*, const char*, ...) ------- <stdio.h>Cette fonction formate la liste des paramètres éventuels à la suite de p2, selon les spécifications de format de p2, la chaine de caractères résultante etant écrite sur le fichier p1. Elle retourne le nombre de caractères écrits ou un nombre négatif sur erreur. Pour écrire sur la sortie standart il faut spécifier le fichier stdout en p1, ce qui donne :

fprintf(stdout, "bonjour"); équivalent à printf("bonjour");

M5.2 Exercices : saisie et affichage de chaines

Exercice 1Faire une fonction qui récupère uniquement les les voyelles d'une chaine entrée par l'utilisateur. La fonction ne stocke jamais la totalité de l'entrée utilisateur mais conserve uniquement les voyelles. tester dans un programme

Exercice 2Ecrire sa propre version de fgets() en utilisant getchar(). Tester dans un programmer

12

Page 13: M5_chaines de Caractères

Exercice 3Ecrire une fonction qui affiche uniquement tous les mots contenant un e dans une phrase entrée par l'utilisateur. La phrase est saisie d'un coup mais les mots sont récupérés un par unet affichés immédiatement s'ils contiennent un e.

exercice 4Faire une fonction qui renvoie la somme des codes ascii des caractères de la chaine. Tester dans un programme.

Exercice 5Le programme choisit un mot dans une liste de mot. L'utilisateur est invité ensuite à écrire une phrase. Le programme indique si les lettres du mot choisi se trouve dans l'ordre dans la phrase entrée. Par exemple si le mot est "tais toi" il est contenu dans "tata Sylvie est montée sur le toit". Les mots peuvent être des codes par exemple "yvtote". Tester.

Exercice 6Découvrir le code secret d'une porte. Le programme compose un code secret composé uniquement de lettres. L'utilisateur doit le découvrir en entrant des phrases ou des lettres. A chaque fois que l'utilisateur trouve une lettre, le programme indique laquelle. Elles doivent être découvertes dans l'ordre. Par exemple si le code est "tarfe", d'abord 't', ensuite 'a', ensuite 'r' etc. Lorsque toutes les lettres sont trouvées, le programme indique que la porte s'ouvre. Tester.

13

Page 14: M5_chaines de Caractères

14

Page 15: M5_chaines de Caractères

3 Opérations de base sur les chaînes

Outre les fonctions de saisie et d’affichage la librairie <stdio.h> contient un grand nombre d’autres fonctions de traitements des chaînes de caractères. Il y a également toutes les fonctions dont le nom commence par str (abréviation de "string", chaîne en anglais) qui font partie de la librairie <string.h>. En voici quelques unes particulièrement pratiques et utiles. La plupart sont relativement faciles à réécrire.

3.1 Modifier

Avant d’aborder les fonctions standards il est intéressant de se remémorer comment manipuler des chaînes soi-même sans aide de fonctions préfabriquées. Voici un exemple de code simple qui convertit les minuscules d’une chaîne en majuscule sans tenir compte des caractères accentués.

int main(int argc, char *argv[]){char buf[100];int i; printf("enter chaine :\n");

fgets(buf,100,stdin); // 1for (i=0; buf[i]!='\0';i++) // 2

if(buf[i]>='a' && buf[i]<='z') buf[i]-=('a'-'A');

puts(buf); // 3 return 0;}

(1) Récupération d’une chaine avec la fonction fgets()(2) Parcours de la chaîne et modification de chaque minuscule rencontrée. Pour passer en majuscule il faut soustraire la différence entre la première minuscule et la première majuscule.(3) Affichage de la chaîne transformée en majuscule.

Autre exemple de conversion d’une chaîne en majuscule avec cette fois l’écriture d’une fonction qui prend en compte tous les caractères accentués dits "spéciaux" . La chaîne originale source et la chaîne résultat destination sont deux chaînes différentes.

void majuscule(char src[], char dest[]) //1{int i; for(i=0; src[i]!='\0'; i++){ switch ((unsigned char)src[i]){ case 133 : // 'à' case 131 : dest[i]='A'; break; // 'â' case 130 : // 'é' case 138 : // 'è' case 136 : dest[i]='E'; break; // 'ê' case 140 : // 'î' case 139 : dest[i]='I'; break; // 'ï' case 147 : dest[i]='O'; break; // 'ô' case 151 : // 'ù' case 150 : dest[i]='U'; break; // 'û' case 135 : dest[i]='C'; break; // 'ç'

15

Page 16: M5_chaines de Caractères

default : if (src[i] >='a' && src[i] <= 'z') dest[i]=src[i]-('a'-'A'); else dest[i]=src[i]; } }}

La fonction majuscule prend en entrée comme paramètres deux tableaux de caractères, c'est à dire deux pointeurs de caractères qui permette de récupérer les adresses des deux chaînes de caractères. Le paramètre src prend la chaîne à transformer en majuscule et le paramètre dest reçoit l’adresse d’une seconde chaîne dans la quelle sera stocké le résultat.

Les deux chaines, supposées de la même taille, sont parcourues et chaque caractère de src est transformé en majuscule copièe dans dans dest. Si le caractère n'est pas une minuscule il est recopié tel quel dans dest. Tous les caractères accentuées sont pris en compte et chacun est orienté vers la majuscule correspondante. Attention le codage ASCII des caractères est fait sur un octet sur une plage total de valeurs de 0 à 255. Pour que ce soit possible il faut que les valeurs soient interprétées en mode non signé, sans le codage du signe (plage de -128 à 127). D'où le cast sur chaque caractère de src dans le switch.Exemple d’appel dans un programme :

int main(int argc, char *argv[]){char buf[100]; printf("enter chaine :\n"); fgets(buf,100,stdin); majuscule(buf,buf); puts(buf); return 0;}

3.2 Récupérer la longueur

size_t strlen(const char*s) ------- <string.h>Cette fonction retourne la longueur de la chaîne passée en paramètre sans compter le ‘\0’ final (si p pointe sur une chaine vide " " strlen retourne 0). De ce fait la taille pour coder une chaîne complète est strlen(s)+1.

Exemple d’utilisation :

char buf[100];int L; printf("enter chaine : "); fgets(buf,100,stdin); L=strlen(buf) printf ("longueur de la chaîne %s : %d\n",buf,L);

Attention, fgets() ajoute un ‘\n’ lorsque l’on tape enter et ce caractère fait partie de la chaîne et compte pour un. Il est visible si l’on affiche la chaîne parce que le curseur d’écriture va passer à la ligne suivante.

16

Page 17: M5_chaines de Caractères

3.3 Copier

char* strcpy(char*, const char*) ------- <string.h>Cette fonction recopie la chaîne de caractères p2 à l’adresse p1 et retourne p1. Attention, la zone mémoire pointée par p1 doit être suffisamment grande et accessible en écriture.

Exemple d’utilisation :

char buf[100];char cpi[100]; printf("enter chaine :\n"); fgets(buf,100,stdin);

strcpy(cpi, buf); printf("copie : %s",cpi);

3.4 Concaténer

char* strcat(char*, const char*) ------- <string.h>Cette fonction concatène la chaîne de caractères p2 à la suite de la chaîne p1 et retourne p1. La zone mémoire pointée par p1 doit être suffisamment grande et accessible en écriture.

Exemple d’utilisation :

char buf[100];char cpi[100];int i; printf("enter chaine :\n"); fgets(buf,100,stdin); // suppression de ‘\n’, avant dernier caractère

buf[strlen(buf)-1]='\0'; // la chaîne est mise trois fois à la suite dans cpi

for (i=0; i<3;i++) strcat(cpi, buf); printf("concat : %s\n",cpi);

3.5 Comparer

int strcmp(const char*, const char*) ------- <string.h>Cette fonction compare les chaînes de caractères p1 et p2 e retourne une valeur négative, nulle ou positive selon que la première est inférieure, égale ou supérieur à la seconde pour l’ordre lexicographique.

Exemple d’utilisation :

char buf[100];char cpi[100];int i; printf("enter deux chaines :\n"); fgets(buf,100,stdin); buf[strlen(buf)-1]='\0'; // suppression ’\n’ avant fin fgets(cpi,100,stdin); cpi[strlen(cpi)-1]='\0'; // suppression ’\n’ avant fin if ( (res=strcmp(cpi,buf))==0) printf ("les chaines sont identiques\n");

17

Page 18: M5_chaines de Caractères

else if(res<0) printf("la chaine %s est avant la chaine %s\n",cpi,buf); else printf("la chaine %s est apres la chaine %s\n",cpi,buf);

M5.2 Exercices : manipulations sur les chaines

Exercice 1Ecrire vos propres versions des fonctions suivantes :

- fgets() /saisir une chaine. - strlen() / compter la longueur de la chaine et retourner le résultat- strcpy() / copier une chaine dans une seconde- strcat() / concaténer deux chaines, la seconde à la suite de la première- strcmp() / comparer deux chaines et donner l'ordre lexicographique

Ensuite dans un programme, tester la différence de rapidité d'exécution entre votre version et celle de la librairie standard (donner les deux vitesses). Faites un menu qui permet de choisir la fonction à tester.

Exercice 2La librairie standart <string.h> fournit d'autres fonctions pour le traitement des chaines. Par exemple les trois fonctions : strncat(), strncmp(), strncpy(). Trouver comment utiliser ces fonctions et dans un programme, donner vous-même un exemple de code qui marche pour chacune des trois.

Exercice 3Faire une fonction qui compte le nombre de mots dans un texte (au choix, le texte est fourni en dur dans le programme ou une phrase assez longue peut être entrée par l'utilisateur). Tester dans un programme qui s'arrête à la demande de l'utilisateur. Faire une deuxième fonction qui compte le nombre de segments obtenus à partir de deux séparateurs quelconques entrés par l'utilisateur.

Exercice 4Faire un programme avec un menu utilisateur qui permet les opérations suivantes tant que l'utilisateur le souhaite, chaque opération est une fonction :

- saisir une chaine- compter le nombre de voyelles dans une chaine en paramètre et retourner le résultat.- compter le nombre de consonnes et retourner le résultat- supprimer toutes les consonnes d'une chaine et modifier la chaine en conséquence- supprimer toutes les voyelles d'une chaine sans modifier l'originale- inverser l'ordre des lettres de la chaine (bonjour -> ruojnob)

. - indiquer si une chaine est un palimdrôme (abccba, anna, azertytreza sont des palindromes)- crypter une chaine avec un décalage circulaire. La valeur de cryptage est entrée par l'utilisateur.- décrypter la chaine si elle est cryptée.

Exercice 5Dans un programme faire une fonction qui affiche la conjugaison au présent de l'indicatif d'un verbe du premier groupe sous la forme :

18

Page 19: M5_chaines de Caractères

je chantetu chantesil/elle chantenous chantonsvous chantezils/elles chantent

Le verbe à conjuguer est entré par l'utilisateur et passé en argument à la fonction.Au départ s'assurer que le verbe fourni se termine bien par "er". On suppose qu'il s'agit d'un verbe régulier et que l'utilisateur ne fournit pas de verbe comme manger (cause nous mongeons et non nous mangons).

Exercice 6Écrire une fonction qui compte le nombre de répétition des lettres utilisées dans un petit texte. La saisie du texte n'est pas faite dans cette fonction. Le résultat est affiché dans le contexte d'appel, après l'exécution de la fonction. Tester dans un programme.

Exercice 7Problème mon clavier est cassé. A chaque fois que je tape sur s, j ou g ça écrit ch. Dans un programme tester une fonction qui remplace toutes les lettres s, j et g d'un petit texte passé en argument en ch : "suppose" devient "chuppoche", "je" devient "che", "fromage" devient "fromache" etc.

Ensuite intégrer dans le programme le fait que l'utilisateur puisse choisir lui-même la transformation à opérer. Faire une deuxième fonction qui prend en plus en argument la lettre à transformer et en quelle autre lettre ou ensemble de lettres elle est transformée.

19