Title: Les chanes de caractres
1Les chaînes de caractères
2Important
- Il nexiste 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)
3Les constantes chaîne
- Suite de caractères placé entre
- Caractères utilisables
- Nimporte quel caractère du jeu de caractère
source - Les caractères de contrôle (\n, \t, \v, )
- Sauf (que lon peut obtenir par \)
- ceci est \correct\
- Sauf fin de ligne (qui doit apparaître sous \n)
- ceci nest pas
- correct
4Convention 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 sagit donc dun caractère de type char.
- Tout se passe comme si la constante chaîne était
un tableau de caractères.
5Exemple
Va sarrê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
-
6Emplacement 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 messbonjour 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 lexécution )
7Risque de modification des constantes chaîne
- char adrbonjour
- adr x / bonjour devient il xonjour?/
- (adr3) w /bonjour devient il bonwour?/
- Soit la chaîne a été placée dans une zone
protégée et une erreur dexécution est levée. - Soit la modification à lieu, que le caractère
visé soit à lintérieur ou à lextérieur de la
chaîne visée!
8Comment 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/ - adri 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 t20 bonjour / (t3)x est
licite /
9Créer, utiliser ou modifier une chaîne
- Le C manque dunité 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é.
10Comment disposer dun 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 quon pourra y ranger. - Soit allouer dynamiquement, au moment de
lexé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.
11Comment agir sur le contenu dune chaîne?
- Linitialiser lors de la réservation de son
espace - char ch20 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 chiffre11
- int i
- for(i0i?10i) chiffrei 0 i
- chiffre10 \0
12Comment agir sur le contenu dune chaîne? (2)
- La modifier globalement avec les fonctions
standard. - Affectation nest pas possible (pas de type
string) mais fonction standard sen charge - char ch110bonjour
- char ch210
- strcpy(ch2,ch1)
- strcpy(ch2,hello)
- Modifier partiellement jouer sur pointeru de
début de chaîne. - char ch120bonjour
- char ch2monsieur
- strcpy(ch12, ch24) / donne bosieur dans ch1
/ - Risques dépasser les limites de la chaîne!
13Comment 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 mot11
- int i
- printf(donner un mot de moins de 10
caractères) - gets(mot)
- for(i0i?strlen(mot)i) printf(c \n,
moti) -
14Comment utiliser une chaîne existante
- Utilisation dune partie dune chaîne caractère
par caractère (cf avant) ou utiliser le
formalisme du tableau - int main(void)
- char chbonjour monsieur
- puts(ch)
- puts(ch8) /ou puts(ch8) /
-
- Donne bonjour monsieur
- monsieur
15Entrée-sorties standard de chaînes
- Etude sur les entrées-sorties standard
généralisable pour tout type de fichier.
16Les sorties
- int puts(const char chaîne) (stdio.h)
- Renvoie à la sortie standard les différents
caractères de la chaîne dadresse 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 dajouter
dautre infos et de modifier la chaîne à
laffichage (nombre de caractères à utiliser)
17Lecture de chaînes
- char gets(char chaine) (stio.h)
- Lire les caractères de lentrée standard en les
rangeant dans ladresse chaîne - Sarrêter dès que \n ou EOF est rencontré.
- Le caractère \n nest pas introduit en mémoire
mais est consommé (retiré du buffer) - Un caractère \0 est ajouté (à prévoir lors de
lallocation de mémoire). - Retourne ladresse de la chaîne si aucune erreur,
NULL sinon
18Lecture 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 nest 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!
19Manipulation 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)
20La fonction strlen
- size_t strlen(const char chaine)
- Fournit la longueur dune chaîne dont on lui a
transmis ladresse en argument. Cette longueur
correspond au nombre de caractères lus depuis
ladresse fournie jusquau caractères de code
nul. (qui nest pas compté).
21Copie de chaîne
- Pas daffectation possible
- Seule possibilité recopier à une adresse donnée
les caractères dune chaîne située à une autre
adresse. - char strcpy(char but, const char source)
- Neffectue aucun contrôle de longueur et ne
sassure pas de la présence dun zéro à la fin - char strncpy(char but, const char source,
size_t longueur) - Si aucun \0 na été trouvé dans source au bout
longueur caractères, il nest pas ajouté but ne
sera pas une chaîne!
22Exemple
- int main(void)
- char ch120 xxxxxxxxxxxxxxxxxxx
- char ch220
- printf(donnez un mot )
- gets(ch2)
- strncpy(ch1,ch2,6)
- printf(s,ch1)
-
- Donne
- donnez un mot bon
- bon\0xxxxxxxxxxxx\0
23Concaténation de chaînes
- int main(void)
- char cha150bonjour
- 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
24Concaténation de chaînes
- char strcat(char but, const char source)
- Neffectue aucun contrôle de longueur
- Ne sassure pas de la présence dun zéro en fin
de chaîne. - Attention aux chaînes qui se chevauchent
- char strncat(char but, const char source,
size_t longueur) - Ne sassure pas de la présence dun zéro en fin
de chaîne. - Attention aux chaînes qui se chevauchent
25Comparaison de chaînes
- On ne dispose pas dopé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
26Recherche dans une chaîne
- Permet de chercher dans une chaîne la première
occurrence - Dun caractère donné (strchr et strrchr)
- Dune autre chaîne (strstr)
- Dun caractère appartenant à un ensemble de
caractère (strpbrk) - Toutes ces fonctions fournissent ladresse de
linformation recherchée si elle existe, NULL
sinon - De plus
- Extraire ou supprimer dune 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)
27Recherche 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
limplémentation) - strchr(bonjour,o) / donne ladresse du
premier o / - char strrchr(const char chaine, int c)
- Même traitement à partir de la fin.
- strrchr(bonjour,o) / donne ladresse du
dernier o /
28Recherche de sous chaîne
- Permet de rechercher la première occurrence dune
chaîne donnée. - char strstr(const char ch1, const char ch2)
- Renvoie ladresse de la premières occurrence ou
NULL.
29Recherche dun caractère parmi plusieurs strpbrk
- char strpbrk(const char ch1, const char ch2)
- Retourne ladresse de la première occurrence dun
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 ch81
- char ad
-
- ad ch
- while(ad strpbrk(ad, ponct)) ad
30Recherche dun préfixe
- size_t strspn(const char ch1, const char ch2)
- Fournit la longueur du segment initial dune
chaîne formée entièrement de caractères
appartenant à un ensemble donné. - strspn(2587abc25,0123456789) vaut 4
- strspn(XYZZYX,XYZ) vaut 6
- size_t strcspn(const char ch1, const char ch2)
- Fournit la longueur initiale dune chaîne formée
entièrement de caractères nappartenant pas à un
ensemble donné. - strcspn(abc25zxt,0123456789) vaut 3
31Fonction 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 ladresse de la première sous-chaîne.
- char adr, ch, delim
-
- adr strtok(ch, delim)
- while(adr)
- adr strtok(adr,delim)
-
-
32Fonctions de conversion dune 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
33Conversion en double strtod
- double strtod(const char ch1, char carinv)
- strtod(12.25,NULL) /donne environ 12.25
(double) / - strtod(-2.2bob,NULL) /donne environ -2.2
(double) / - strtod( -1.5,NULL) /donne environ -1.5
(double) / - char ad_car
- strtod( 12e25bonjour,ad_car)
- /donne environ 12e25 (double) et on obtient
dans ad_car ladresse de b/
34strtol 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
35atof, atoi et atod
- double atof(const char ch1)
- long atol(const char ch2)
- int atoi(const char ch3)
36Fonctions de manipulation de suites doctets.
- Permet de recopier des objets dont on connaît
ladresse et la taille sans pour autant connaître
le type. (string.h) - Fonctions de recopie memcpy, memmove
- Fonction de comparaison memcmp
- Fonction dinitialisation memset
- Fonction de recherche dans une suite doctets
memchr
37Exercice
- Ecrire une fonction lireLigne qui lit au plus lim
caractères de lentré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)
38Correction
- int lireLigne(char s, int lim)
- int c, i
- for(i0
- i?lim-1 (cgetchar()) ! EOF) c !\n
i) si c - if(c \n) si c i
- si \0
- return i
39Exercice
- 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
- ji0
- while(si \0) i
- --i
- if(si \n) --i
- while(j?i)
- tempsj
- sj si
- si temp
- --i
- j
-
-
41Exercice
- Ecrivez la fonction strlen
- int strlen(char s)
42Correction
- int strlen(char s)
- int n
- for(n0 s ! \0 s)
- n
- return n
-