Télécharger la présentation
La présentation est en train de télécharger. S'il vous plaît, attendez
1
Les chaînes de caractères
2
Important Il n’existe PAS de type ``chaîne de caractère`` en C
Une abstraction de chaîne de caractère est donnée par un tableau de caractères Une chaîne de caractères valide est obligatoirement terminé par le caractère NULL ( i.e. \0)
3
Les constantes chaîne Suite de caractères placé entre ``
Caractères utilisables: N’importe quel caractère du jeu de caractère source Les caractères de contrôle (\n, \t, \v, …) Sauf `` (que l’on peut obtenir par \``) ``ceci est \``correct\`` `` Sauf fin de ligne (qui doit apparaître sous \n) ``ceci n’est pas correct ``
4
Convention de représentation des constantes chaîne
Le compilateur représente une chaîne sous une forme de tableau de manière conventionnée: ``bonjour`` amènera le compilateur à placer en mémoire la suite des caractères `b`,`o`,`n`,`j`,`o`,`u`,`r`,`\0` selon le norme, la notation sera convertie en un pointeur sur le premier caractère. Il s’agit donc d’un caractère de type char*. Tout se passe comme si la constante chaîne était un tableau de caractères.
5
Exemple #include stdio.h int main(void){ char *adr;
Va s’arrêter lorsque \0 va être atteint Ne va afficher que ``bonjour`` #include stdio.h int main(void){ char *adr; adr = ``bonjour \0 Monsieur``; while(*adr){ printf(``%c``,*adr); adr++; }
6
Emplacement mémoire Une constante chaîne peut apparaître dans le programme source au niveau Global: Elle figure dans une initialisation ou une instruction de déclaration: char *mess=``bonjour``; ou char t[]= ``hello``; Remarque: t est une constante pointeur, t = ``salut ``; est interdit Local: Dans une déclaration ou dans une instruction: strcpy(adr,``salut``); Une constante chaîne est toujours placée en mémoire statique (alloué une fois pour toute avant l’exécution )
7
Risque de modification des constantes chaîne
char *adr=``bonjour``; *adr = `x`; /* bonjour devient il xonjour?*/ *(adr+3) = `w`; /*bonjour devient il bonwour?*/ Soit la chaîne a été placée dans une zone protégée et une erreur d’exécution est levée. Soit la modification à lieu, que le caractère visé soit à l’intérieur ou à l’extérieur de la chaîne visée!
8
Comment se protéger? Déclarer les pointeurs constant.
const char *adr = ``bonjour``; Interdit la modification de la chaîne pointée (adr est un pointeur sur un objet constant.) *adr = `x`; /*provoque une erreur de compilation*/ adr[i] = `x`; /*aussi*/ Mais toujours problème avec: scanf(``%s``,adr); et recopiage du pointeur dans un pointeur non constant (warning compilation) Remarque: pas de problème avec char t[20] = ``bonjour``; /* *(t+3)=`x`; est licite */
9
Créer, utiliser ou modifier une chaîne
Le C manque d’unité quand à la manipulation des chaînes, on peut: Utiliser les fonctions de la bibliothèque standard qui travaillent sur la chaîne en se basant sur son zéro de fin. Manipuler individuellement chaque caractère (comme un parcours de tableau) dans ce cas; la détection de fin de chaîne est de votre responsabilité.
10
Comment disposer d’un emplacement pour y ranger une chaîne?
Soit utiliser un tableau de caractères existant (déclaré), ce qui impose une taille maximale pour la chaîne de caractère qu’on pourra y ranger. Soit allouer dynamiquement, au moment de l’exécution un emplacement de la taille exacte de la chaîne à enregistrer. Dans les deux cas, le formalisme de manipulation de la chaîne est le même.
11
Comment agir sur le contenu d’une chaîne?
L’initialiser lors de la réservation de son espace char ch[20] = ``bonjour``; (les 12 autres sont inconnus) Créer ou modifier individuellement chacun de ses caractères (ne pas oublier le caractère NULL en fin de chaîne) int main(void){ char chiffre[11]; int i; for(i=0;i10;i++) chiffre[i] = `0`+ i; chiffre[10] = `\0`; }
12
Comment agir sur le contenu d’une chaîne? (2)
La modifier globalement avec les fonctions standard. Affectation n’est pas possible (pas de type string) mais fonction standard s’en charge: char ch1[10]=``bonjour``; char ch2[10]; strcpy(ch2,ch1); strcpy(ch2,``hello``); Modifier partiellement: jouer sur pointeru de début de chaîne. char ch1[20]=``bonjour``; char *ch2=``monsieur``; strcpy(ch1+2, ch2+4); /* donne bosieur dans ch1 */ Risques : dépasser les limites de la chaîne!
13
Comment utiliser une chaîne existante
Caractère par caractère: quelle que soit la méthode utilisée pour créer la chaîne (allocation dynamique ou statique) le formalisme est le même: int main(void){ char mot[11]; int i; printf(``donner un mot de moins de 10 caractères:``); gets(mot); for(i=0;istrlen(mot);i++) printf(``%c \n``, mot[i]); }
14
Comment utiliser une chaîne existante
Utilisation d’une partie d’une chaîne: caractère par caractère (cf avant) ou utiliser le formalisme du tableau: int main(void){ char ch[]=``bonjour monsieur``; puts(ch); puts(&ch[8]); /*ou puts(ch+8) */ } Donne: bonjour monsieur monsieur
15
Entrée-sorties standard de chaînes
Etude sur les entrées-sorties standard généralisable pour tout type de fichier.
16
Les sorties int puts(const char *chaîne); (stdio.h)
Renvoie à la sortie standard les différents caractères de la chaîne d’adresse chaîne, zéro de fin non compris puis transmet un caractère \n. Sa valeur de retour est non négative si tout se passe bien, EOF si une erreur. int printf(``%s``,*char); Ici, on ajoute pas de \n. Permet d’ajouter d’autre infos et de modifier la chaîne à l’affichage (nombre de caractères à utiliser…)
17
Lecture de chaînes char *gets(char *chaine); (stio.h)
Lire les caractères de l’entrée standard en les rangeant dans l’adresse chaîne S’arrêter dès que \n ou EOF est rencontré. Le caractère \n n’est pas introduit en mémoire mais est consommé (retiré du buffer) Un caractère \0 est ajouté (à prévoir lors de l’allocation de mémoire). Retourne l’adresse de la chaîne si aucune erreur, NULL sinon
18
Lecture de chaîne (2) Avec scanf et %s
On ne peut pas lire de chaîne commençant par un espace blanc (tabulation, espaces, …). Les espaces blancs sont utilisés comme délimiteurs. Il n’est donc pas possible de lire une chaîne contenant une espace! Le délimiteur est lu mais pas consommé: il reste disponible pour la prochaine lecture. scanf(``%s``,ch1); gets(ch2); avec bonjour donnera ``bonjour`` dans ch1 et une chaîne vide dans ch2!
19
Manipulation de chaînes
Fonctions standard de manipulation (string.h): Copie de chaîne Concaténation de chaîne Comparaison de chaîne Recherche de caractères Conversion en nombres Travaillent toujours par adresse (attention aux tailles des espaces)
20
La fonction strlen size_t strlen(const char *chaine)
Fournit la longueur d’une chaîne dont on lui a transmis l’adresse en argument. Cette longueur correspond au nombre de caractères lus depuis l’adresse fournie jusqu’au caractères de code nul. (qui n’est pas compté).
21
Copie de chaîne Pas d’affectation possible
Seule possibilité: recopier à une adresse donnée les caractères d’une chaîne située à une autre adresse. char *strcpy(char *but, const char *source) N’effectue aucun contrôle de longueur et ne s’assure pas de la présence d’un zéro à la fin char *strncpy(char *but, const char *source, size_t longueur) Si aucun \0 n’a été trouvé dans source au bout longueur caractères, il n’est pas ajouté: but ne sera pas une chaîne!
22
Exemple int main(void){ char ch1[20] = ``xxxxxxxxxxxxxxxxxxx``;
printf(``donnez un mot: ``); gets(ch2); strncpy(ch1,ch2,6); printf(``%s``,ch1); } Donne: donnez un mot: bon bon\0xxxxxxxxxxxx\0
23
Concaténation de chaînes
int main(void){ char cha1[50]=``bonjour``; const char *ch2 = `` monsieur``; printf(``avant: %s \n``,ch1); strcat(ch1,ch2); printf(``après: %s \n``,ch1); } Donne: avant: bonjour après: bonjour monsieur
24
Concaténation de chaînes
char *strcat(char *but, const char *source); N’effectue aucun contrôle de longueur Ne s’assure pas de la présence d’un zéro en fin de chaîne. Attention aux chaînes qui se chevauchent char *strncat(char *but, const char *source, size_t longueur);
25
Comparaison de chaînes
On ne dispose pas d’opérateur relationnels sur les chaînes de caractères (reviendrait à comparer des pointeurs…) int strcmp(const char *ch1, const char *ch2) int strncmp(const char *ch1, const char *ch2, size_t longueur) Effectuent une comparaison lexicographique La valeur de retour est positive si ch1 arrive avant ch2, nulle si elles sont égales et négative sinon
26
Recherche dans une chaîne
Permet de chercher dans une chaîne la première occurrence : D’un caractère donné (strchr et strrchr) D’une autre chaîne (strstr) D’un caractère appartenant à un ensemble de caractère (strpbrk) Toutes ces fonctions fournissent l’adresse de l’information recherchée si elle existe, NULL sinon De plus: Extraire ou supprimer d’une chaîne un préfixe formé de certains caractères D’éclater une chaîne en plusieurs parties, en utilisant comme séparateurs des caractères de son choix (strspn, strcspn, strtok)
27
Recherche de carctères
char *strchr(const char *chaine, int c); Permet de rechercher la première occurrence du caractère c (un int, pour ne pas se préoccuper de l’implémentation) strchr(``bonjour``,`o`); /* donne l’adresse du premier `o` */ char *strrchr(const char *chaine, int c); Même traitement à partir de la fin. strrchr(``bonjour``,`o`); /* donne l’adresse du dernier `o` */
28
Recherche de sous chaîne
Permet de rechercher la première occurrence d’une chaîne donnée. char *strstr(const char *ch1, const char *ch2); Renvoie l’adresse de la premières occurrence ou NULL.
29
Recherche d’un caractère parmi plusieurs : strpbrk
char *strpbrk(const char *ch1, const char *ch2); Retourne l’adresse de la première occurrence d’un des caractères de la chaîne ch2 dans la chaîne ch1 ou NULL. Exemple: remplacer les signes de ponctuations par un espace char ponct[] =``.,;:!?``; char ch[81]; char *ad; … ad =ch; while(ad = strpbrk(ad, ponct)) *ad=` `;
30
Recherche d’un préfixe
size_t strspn(const *char ch1, const char *ch2); Fournit la longueur du ``segment initial`` d’une chaîne formée entièrement de caractères appartenant à un ensemble donné. strspn(``2587abc25``,`` ``); vaut 4 strspn(``XYZZYX``,``XYZ``); vaut 6 size_t strcspn(const *char ch1, const char *ch2); Fournit la longueur initiale d’une chaîne formée entièrement de caractères n’appartenant pas à un ensemble donné. strcspn(``abc25zxt``,`` ``); vaut 3
31
Fonction d’éclatement
Eclater une chaîne en plusieurs sous-chaînes si on connaît les caractères de séparation. ``12h 45mn 42s`` en ``12``, ``45`` et ``42`` char *strtok(char *ch, const char *delimit) Renvoie l’adresse de la première sous-chaîne. char *adr, *ch, *delim; … adr = strtok(ch, delim); while(*adr){ adr = strtok(adr,delim); }
32
Fonctions de conversion d’une chaîne en nombre
Fonctions universelles: strtol, strtoul, strtod Fonctions issue des premières implémentation: atoi, atof, atol conservées pour compatibilité Pas de fonction inverse (sprintf) Conversion en bloc de plusieurs strings par sscanf
33
Conversion en double: strtod
double strtod(const char *ch1, char **carinv); strtod(``12.25``,NULL); /*donne environ (double) */ strtod(``-2.2bob``,NULL); /*donne environ -2.2 (double) */ strtod(`` ``,NULL); /*donne environ -1.5 (double) */ char *ad_car; strtod(`` 12e25bonjour``,&ad_car); /*donne environ 12e25 (double) et on obtient dans ad_car l’adresse de `b`*/
34
strtol et strtoul long strtol(const char *ch, char **carinv, int base)
unsigned long strtoul(const char *ch, char **carinv, int base) Base précise la base dans laquelle le nomre est supposé être écrit. Si nul: en décimal
35
atof, atoi et atod double atof(const char *ch1);
long atol(const char *ch2); int atoi(const char *ch3);
36
Fonctions de manipulation de suites d’octets.
Permet de recopier des objets dont on connaît l’adresse et la taille sans pour autant connaître le type. (string.h) Fonctions de recopie memcpy, memmove Fonction de comparaison memcmp Fonction d’initialisation memset Fonction de recherche dans une suite d’octets memchr
37
Exercice Ecrire une fonction lireLigne qui lit au plus lim caractères de l’entrée standard et les retourne dans une chaîne jusqu’à la lecture de \n faire en sorte que la chaîne de sortie soit une chaîne! Renvoyer la longueur de la chaîne int lireLigne(char s[], int lim)
38
Correction int lireLigne(char s[], int lim){ int c, i; for(i=0;
ilim-1 && (c=getchar()) != EOF) && c !=`\n`; i++) s[i] =c; if(c == `\n`){ s[i] = c; ++i;} s[i] = `\0`; return i; }
39
Exercice Ecrire une fonction qui inverse une chaîne de caractère
void inverser(char s[]);
40
void inverser(char s[]){
int i,j; char temp; j=i=0; while(s[i] == `\0`) ++i; --i; if(s[i] == `\n`) --i; while(ji){ temp=s[j]; s[j] = s[i]; s[i] = temp; ++j; }
41
Exercice Ecrivez la fonction strlen int strlen(char *s);
42
Correction int strlen(char *s){ int n; for(n=0; *s != `\0`; s++) n++;
return n; }
Présentations similaires
© 2024 SlidePlayer.fr Inc.
All rights reserved.