Sunteți pe pagina 1din 56

Les Pointeurs en C

A. EL ALLAOUI
1
Les pointeurs
Aujourd’hui, vous allez étudier :
● La définition d’un pointeur
● L’utilisation des pointeurs
● La déclaration et l’initialisation des pointeurs
● L’utilisation des pointeurs avec des variables simples et
des tableaux
● Opérateurs unaires pour manipuler les pointeurs
● Passage de paramètres de fonction par référence
● Le passage des tableaux à une fonction avec les
pointeurs
2
● Utilisation des pointeurs avec les chaines de caractères
Les Pointeurs en C
Les pointeurs jouent un rôle très important dans le langage C.
Ils permettent de manipuler les données dans vos programmes.

- Pour devenir un bon programmeur en langage C, il est impératif de


bien comprendre les principes de fonctionnement des pointeurs.

- Quand votre ordinateur fonctionne, une partie de sa mémoire vive


est occupée par le système d’exploitation.

- Si vous lancez un programme, le code (les instructions en langage


machine) et les données qu’il utilise occuperont en partie cette
mémoire.
3
Les pointeurs, c'est quoi?
Un pointeur est une variable particulière, dont
la valeur est l'adresse d'une autre variable.
• Pointeur p: valeur 5A0F3 (adresse
hexadécimale)
• Adresse 5A0F3: valeur 17 (correspondant à la
valeur d'un entier i)
i=17 5A0F3 17

p=5A0F3 p i
En accédant à cette adresse, on peut accéder indirectement à la variable et donc la modifier.

Un pointeur est une adresse mémoire. On dit que le pointeur p


pointe vers i, puisque p pointe vers l’emplacement mémoire où 4
est enregistrée i.
MÉMOIRE CENTRALE ET ADRESSES

La mémoire centrale d’un ordinateur est composée d’un très grand nombre
d’octets. Chaque octet est repéré par un numéro appelé adresse de l’octet.

adresse bits
Octet 0

Octet 1

Octet 2

p Adress p 5 A 0 F 3

Octet 2n+2

i 5A0F3 0 0 0 0 0 1 1 1
Octet 2n+1
5
Les pointeurs: pourquoi ?
• Les pointeurs sont nécessaires pour:
– effectuer les appels par référence (i.e. écrire
des fonctions qui modifient certains de leurs
paramètres)

– manipuler des structures de données


dynamiques (liste, pile, arbre,…)

– allouer dynamiquement de la place mémoire

6
L’étape suivante consiste à stocker l’adresse de vari dans la variable p_vari
en langage C, p_vari pointe sur vari, ou p_vari est un pointeur vers vari

p_vari vari

En résumé

Un pointeur est une variable qui contient l’adresse d’une autre


variable.
7
Déclaration de Pointeurs
Le symbole * est utilisé entre le type et le nom du
pointeur
• Déclaration d’un entier: int i;
 Déclaration d’un pointeur vers un entier:
int *p;
Exemples de déclarations de pointeurs
int *pi; /* pi est un pointeur vers un int
*pi désigne le contenu de l'adresse */
float *pf; /* pf est un pointeur vers un float */

char c, d, *pc; /* c et d sont des char*/


/* pc est un pointeur vers un char */
double *pd, e, f; /* pd est un pointeur vers un double*/
/* e et f sont des doubles */
double **tab; /* tab est un pointeur pointant sur un pointeur qui
8
pointe sur un flottant double */
Exemple 1
#include <stdio.h>
int main(void)
{
int x = 2; /* déclaration d’une variable x */
int *p; /* déclaration d’un pointeur p */
p = &x; /* p pointe sur x */
/* la valeur de p est l’adresse de x */
scanf("%d", p); /* lecture de la valeur de x au clavier */
printf("%d", x); /* affichage de la nouvelle valeur de x */
return 0;
}

RQ: Ne pas confondre l’usage de l’étoile lors de la


déclaration d’une variable de type pointeur avec l’usage
de l’étoile qui permet d’accéder à l’objet pointé par le
pointeur.

*p = 3; /* l’objet pointé par p prend pour valeur 3 */


9
Exemple 2
#include <stdio.h>
int main(void)
{
int x=2;
int *p = &x; /* x et *p deviennent synonymes */
*p = 3;
printf("La nouvelle valeur de x est %d \n", x );
return 0;
}
/* doit afficher la valeur 3 */

10
Exemple 3
#include <stdio.h>
int main(void)
{
int x=2;
int *p = &x; /* x et *p deviennent synonymes */
printf("La valeur de x est %d\n", *p); /* affiche 2 */
x=5;
printf("La nouvelle valeur de x est %d\n", *p );
/* doit afficher la valeur 5 */
return 0;
} /* doit afficher la valeur 5 */

11
Opérateurs unaires pour manipuler les pointeurs,
& (adresse de) et * (contenu)
Exemple: int i = 8;
printf("VOICI i: %d\n",i);
printf("VOICI SON ADRESSE EN HEXADECIMAL: %p\n",&i);

nom_de_Pointeur = &nom_de_variable
void main(void)
p c
{
0x1132 'a'
char c = 'a', d = 'z';
0x1132
char *p;
p d
0x91A2 'z'
*p = c; 0x91A2
p = &c;
printf("%c\n", *p);
p = &d; L’opérateur * (“valeur pointée par”)
printf("%c\n", *p);
} a
z 12
#include <stdio.h> Exercice
void main() {
int *p, x, y;
p = &x; /* p pointe sur x */
x = 10; /* x vaut 10 */
y = *p - 1; printf(" y= *p - 1 =? = %d\n" , y); y vaut ?
*p += 1; printf(" *p += 1 =? *p = x= ? = %d %d\n" , *p, x); x vaut ?
(*p)++; printf(" (*p)++ =? *p = x= ? = %d %d alors y=%d \n" , *p, x, y);
incrémente aussi de 1 la variable pointée par p, donc x vaut ??.
y vaut 9

*p=0; printf(" *p=0 x=? = %d\n" , x);


comme p pointe sur x, maintenant x vaut ?

*p++; *p=20; printf(" *p++ x=? = %d\n" , x);


} comme p ne pointe plus sur x, x vaut 13
tjr ?
Utiliser des pointeurs
• On peut donc accéder aux éléments par pointeurs en
faisant des calculs d’adresses (addition ou soustraction)

long v[6] ={1,2, 3,4,5,6 };


long p += 4
p++
*p; 1
2 p
p = v; // v==&v[0] 6 1000 1 2 3 4 5 6
printf("%ld\n", *p); v
1000 1008 1016
p++; 1004 1012 1020
printf("%ld\n", *p);
p += 4;
printf("%ld\n", *p);

14
* et ++
*p++ signifie: int a[]={0,1,5};
*p++ trouver la valeur pointée int*p; !
p=a;//&a[0]==a
*p++ passer à l’adresse suivante Int b=*p++;// p 100 104 108

(*p)++ signifie: a 0 1 5

(*p)++ trouver la valeur pointée (*p)++; //*p==3


Int c= (*p)++;
(*p)++ incrémenter cette valeur (sans changer
le pointeur) p 100 104 108

*++p signifie: a 0 2 5

*++p incrémenter d’abord le pointeur


Int d= *++p;
*++p trouver la valeur pointée p 100 104 108

a 0 2 5

15
Exercice

• int t[] = {2,5,7};


• int *p = t;
• int a, b, c ; //*p=
• b = *p++; // b =
• b = *p; // b =
• a = (*p)++; // a=
• c = *++p // c =
16
En résumé, lorsque p pointe sur x, la valeur de p est l’adresse
de x, toute modification de *p modifie x et toute modification
de x modifie *p.
La raison est que *p et x sont sur le même emplacement
mémoire dans la mémoire RAM.

Conseils
À faire
Veillez à bien comprendre ce que représente un pointeur
et comment il travaille. Le langage C et les pointeurs vont de pair.
À ne pas faire
N’utilisez pas un pointeur qui n’a pas été initialisé. Les résultats
pourraient être désastreux

17
Pointeurs et types de variables
Les différents types de variables du langage C n’occupent pas tous la même
mémoire (int prend quatre octets, une variable double en prend huit, etc)

int vint = 12252;


char vchar = 90; //asci de Z
double vdouble = 1200.156004;

La variable int occupe quatre octets,


la variable char en occupe un,
et la variable double huit.

18
Voici la déclaration et l’initialisation des pointeurs vers ces trois variables :
int *p_vint;
char *p_vchar;
double *p_vdouble;
/* des instructions peuvent être insérées ici */
p_vint = &vint;
p_vchar = &vchar;
p_vdouble = &vdouble;

19
Passage des paramètres par valeur et par
adresse
Syntaxe qui conduit à une erreur: Syntaxe correcte:
a et b:
#include <stdio.h> variables #include <stdio.h>
locales à
void ech(int x,int y) void ech(int *x,int *y)
main(). La
{ {
int tampon; fonction ech int tampon;
tampon = x; ne peut donc tampon = *x;
x = y; pas modifier *x = *y;
y = tampon; leur valeur. *y = tampon;
} On le fait }
donc en
void main() passant par void main()
{ {
l'adresse de
int a = 5 , b = 8; int a = 5 , b = 8 ;
ech(a,b); ces variables. ech(&a,&b);
printf(“ a=%d\n ”, a) ; a = ? printf(“ a=%d\n ”, a) ; a=?
printf(“ b=%d\n ”, b) ;
b=?
printf(“ b=%d\n ”, b) ; b=?
} }
PASSAGE DES PARAMETRES PASSAGE DES PARAMETRES
PAR VALEUR PAR ADRESSE
20
Passage de paramètre par valeur
Lorsqu’on passe un paramètre à une fonction, la fonction ne peut pas modifier la
variable. La variable est automatiquement recopiée et la fonction travaille sur une
copie de la variable. La modification de la copie n’entraîne pas une modification de
la variable originale. C’est le passage de paramètre par valeur.

Exemple:
#include <stdio.h>
void NeModifiePas(int x)
{
x = x+1; /* le x local est modifié, pas le x du main */
}
int main(void)
{
int x=1;
NeModifiePas(x);
printf("%d", x); /* affiche 1 : valeur de x inchangée */
return 0;
} 21
Passage de paramètre par adresse

L’idée du passage par adresse est que, pour modifier une variable par un
appel de fonction, il faut passer en paramètre non pas la variable, mais
un pointeur qui pointe sur la variable.

Ainsi, le paramètre est l’adresse de x. Lorsqu’on modifie la mémoire à


cette adresse, la donnée x est modifiée, car on travaille bien sur
l’emplacement mémoire de x

22
Exemple (PASSAGE DE PARAMÈTRE PAR ADRESSE)

#include <stdio.h>
/* la fonction suivante prend en paramètre un pointeur */
void Modifie(int *p)
{
*p = *p+1; /* p pointe sur x, la copie de p aussi */
/* le x du main est modifié */
}
int main(void)
{
int x=1; /* la varible x n’est pas un pointeur */
int *p;
p = &x; /* pointeur qui pointe sur x */
Modifie(p);
printf("%d", x); /* affiche 2 */
return 0;
}
23
Exemple (PASSAGE DE PARAMÈTRE PAR ADRESSE)
RQ: L’utilisation explicite d’un pointeur dans le main est superflue, on peut
passer directement l’adresse de x à la fonction, sans avoir besoin de
définir une variable de type pointeur dans le main.
#include <stdio.h>
void Modifie(int *p) /* paramètre de type pointeur */
{
*p = *p+1; /* ce pointeur p a pour valeur &x (x du main) */
}
int main()
{
int x=1;
Modifie(&x); /* on passe directement l’adresse de x */
printf("%d", x); /* affiche 2 */
return 0;
}
Exemple
La fonction scanf, qui lit des variables au clavier, doit modifier le contenu
de ces variables. Pour cette raison, les variables sont passées à scanf par24
adresse, ce qui explique la nécessité des & devant les variables.
Pointeurs et tableaux
Les pointeurs sont très utiles pour travailler avec les variables, mais ils le
sont encore plus quand on les utilise avec les tableaux. En fait, les index
de tableaux ne sont rien d’autre que des pointeurs.

Noms de tableau et pointeurs


Un nom de tableau sans les crochets s’utilise la plupart du temps comme
un pointeur vers le premier élément du tableau. Si vous avez déclaré le
tableau T[] , T aura la valeur de l’adresse de T [0] et sera donc
équivalent à l’expression &T[0].
T------------------------------------ &T [0]
T+1 -------------------------------- &T [1]
T+i -------------------------------- &T[i]
T[i]---------------------------------- * (T+i)
nous obtenons les relations suivantes :
*(T) == T[0]
*(T+1) == T[1]
*(T+2) == T[2]
etc. 25
*(T+i) == T[i]
Stockage des éléments d’un tableau

Les éléments d’un tableau sont stockés dans des emplacements mémoire
séquentiels, le premier élément ayant l’adresse la plus basse.

26
Stockage des éléments d’un tableau

Conclusion
Vous pouvez constater, à partir de ces exemples, qu’un pointeur devra
être incrémenté de quatre pour accéder à des éléments successifs d’un
tableau de type int, et de huit dans le cas d’un tableau de type double.

Généralement
Pour accéder à des éléments successifs d’un tableau contenant un
type de donnée particulier, le pointeur devra être incrémenté de la
valeur sizeof (typedonnée).

L’opérateur sizeof renvoie la taille en octets du type de donnée reçu


en argument.
RQ:
Le C ne manipule simplement que des tableaux 1D (des vecteurs).
 Il s’ensuit qu’un tableau 2D (matrice) sera considéré
comme un vecteur dont chaque élément est un vecteur.
27
 Ce principe peut être étendu à des tableaux à n entrées
EXP : Création d’un tableau de taille quelconque

#include <stdio.h> // pour la fonction printf()


#include <stdlib.h> // pour la fonction malloc()

void main(){
int i , dim; // compteur et taille du tableau
long* tableau; // pointeur pour stocker l’adresse du tableau

scanf (“%d”, &dim); // saisie par l'utilisateur de la taille du tableau


tableau = (long*) malloc(dim * sizeof(long)); //allocation (dynamique) du tableau
// remplissage du tableau, on utilise les indices 0 à (dim -1)
for (i = 0; i < dim; i++)
tableau[i] = i;
// affichage du contenu du tableau
for (i = 0; i < dim; i++)
printf("%ld\n", tableau[i]);

// destruction du tableau : libération de la mémoire réservée


free(tableau); 28
}
Un nom de tableau est un pointeur constant
Cas des tableaux à plusieurs indices
Comme pour les tableaux à un indice, l’identificateur d’un tableau, employé
seul, représente toujours son adresse de début.
Toutefois, si l’on s’intéresse à son type exact, il ne s’agit plus d’un pointeur sur
des éléments du tableau.

Lorsque le compilateur rencontre une déclaration telle que :


int t[4] [5] ;

t désigne un tableau de 4 éléments, chacun de ces éléments étant lui-


même un tableau de 5 entiers.
Autrement dit, si t représente bien l’adresse de début de notre tableau t, il
n’est plus de type int * mais d’un type « pointeur sur des blocs de 4 entiers »

t+1correspond à l’adresse de t, augmentée de 4 entiers (et non plus d’un


seul !).
29
Un nom de tableau est un pointeur constant
Cas des tableaux à plusieurs indices
Un tableau à plusieurs dimensions est un pointeur de pointeur.

les notations t et &t[0][0] correspondent toujours à la même adresse


t[0] représente l’adresse de début du premier bloc (de 5 entiers) de t,
« Pointeurs » vers des ve
t[1], celle du second bloc... tableau 1D dont chaque
0 1 2 3 « pointe » vers un vecte

0 0 0 0 t[2][4],
1 1 1 1
t[2] est l’adresse
2 2 2 2 du début du vecteu
les notations suivantes sont 4 4 4 d’indice 2, c’est un
4 pointeur vers t[2][0]
totalement équivalentes : 5 5 5 5
t[0] équiva &t[0][0]
t[1] équiva &t[1][0]
Espace de stockage du tableau 30
Les opérateurs réalisables sur des pointeurs
Pointeur arithmétique
Nous venons de voir que le pointeur du premier élément d’un tableau doit être
incrémenté d’un nombre d’octets égal à la taille des données du tableau pour
pointer sur l’élément suivant. Pour pointer sur un élément quelconque en
utilisant une notation de type pointeur, on utilise le pointeur arithmétique.
Incrémenter les pointeurs
Incrémenter un pointeur consiste à en augmenter la valeur. Si vous
incrémentez un pointeur de 1, le pointeur arithmétique va augmenter sa valeur
pour qu’il accède à l’élément de tableau suivant.

Exemple
Si ptr_int pointe sur un élément de tableau de type int, l’instruction suivante :
ptr_int++; incrémente la valeur de ce pointeur de 4 pour qu’il pointe sur
l’élément int suivant.

De la même façon, si vous augmentez la valeur du pointeur de n, C va


incrémenter ce pointeur pour qu’il pointe sur le n-ième élément suivant :
ptr_int += 2;
Cette instruction va augmenter de 8 la valeur du pointeur, pour qu’il pointe312
éléments plus loin.
Les opérateurs réalisables sur des pointeurs

Décrémenter les pointeurs

La décrémentation des pointeurs suit le même principe que


l’incrémentation. Si vous utilisez les opérateurs (– –) ou (– =) pour
décrémenter un pointeur, le pointeur arithmétique va diminuer sa valeur
automatiquement en fonction de la taille des données pointées.

Exemple
ptr_int - - ;
ptr_int - = 2;

32
Les opérateurs réalisables sur des pointeurs
La comparaison de pointeurs
Les opérateurs de comparaison = =, !=, >, <, >=et <= peuvent aussi être
utilisés. Les premiers éléments d’un tableau ont toujours une adresse plus
basse que les derniers. Ainsi, si ptr1et ptr2 sont deux pointeurs d’un même
tableau, la comparaison :
ptr1 < ptr2 : est vraie si ptr1 pointe sur un élément d’index plus petit que
ptr2.
Par exemple, voici, en parallèle, deux suites d’instructions réalisant la
même action : mise à 1 des 10 éléments du tableau t :

33
Les opérateurs réalisables sur des pointeurs

Autre utilisation des pointeurs


La dernière opération que l’on peut effectuer avec des pointeurs est la
différence entre deux pointeurs. Si vous avez deux pointeurs sur un même
tableau, le résultat de leur soustraction correspond au nombre d’éléments les
séparant.
Exemple :
ptr1 – ptr2 : donne le nombre d’éléments qui séparent les deux éléments
pointés par ptr1et ptr2.

Beaucoup d’opérations arithmétiques sont réservées aux variables simples,


car elles n’auraient aucun sens avec les pointeurs. Par exemple, si ptr est un
pointeur, l’instruction :
ptr *= 2; générera un message d’erreur.

34
Le Tableau vous donne la liste des six opérations possibles avec les pointeurs.

Description
Opérateur
Affectation Vous pouvez attribuer une valeur à un pointeur. Cette valeur doit
correspondre à une adresse obtenue avec l’opérateur d’adresse (&,), ou à
partir d’un pointeur constant.

Indirection L’opérateur indirect (*) donne la valeur stockée à l’emplacement pointé.

Adresse de Vous pouvez utiliser l’opérateur d’adresse (&)pour trouver l’adresse d’un
pointeur et obtenir un pointeur vers un pointeur.
Incrément On peut ajouter un nombre entier à la valeur d’un pointeur pour pointer
sur un emplacement mémoire différent.
Décrément On peut soustraire un entier à la valeur d’un pointeur pour pointer sur un
emplacement mémoire différent.
Différence Vous pouvez soustraire un entier de la valeur d’un pointeur pour pointer
sur un emplacement mémoire différent.

Comparaison Ces opérateurs ne sont valides que pour deux pointeurs d’un même
tableau. 35
Précautions d’emploi

Quand vous utilisez des pointeurs dans un programme, une grosse


erreur est à éviter : utiliser un pointeur non initialisé à gauche d’une
instruction d’affectation. Par exemple, dans la déclaration suivante :
int *ptr;
le pointeur n’est pas initialisé. Cela signifie qu’il ne pointe pas sur un
emplacement connu.
Si vous écrivez :
*ptr = 12;
la valeur 12 va être stockée à l’adresse (inconnue) pointée par ptr. Cette
adresse peut se situer n’importe où en mémoire, au milieu du code du
système d’exploitation par exemple.
La valeur 12 risque d’écraser une donnée importante, et le résultat peut
aller de simples erreurs dans un programme à l’arrêt complet du
système.
À ne pas faire
Effectuer des opérations mathématiques comme des divisions, des
multiplications ou des modulos avec des pointeurs. Les seules
opérations possibles sont l’incrémentation ou le calcul de la différence 36
entre deux pointeurs d’un même
Fonctions permettant la manipulation des chaînes
string.h ou stdlib.h

void *strcat(char *chaine1,char *chaine2)


//Concatène les 2 chaînes, résultat dans chaine1.
void *strcpy(char *chaine1,char *chaine2)
//Copie la chaine2 dans chaine1. + '\0‘
void *strncpy(char *chaine1,char *chaine2, NCmax)
// idem strcpy mais limite la copie au nombre de caractères NCmax.
int strcmp(char *chaine1,char *chaine2)
//Compare les chaînes de caractères chaine1 et chaine2,
renvoie un nombre:
- positif si la chaîne1 est supérieure à la chaine2 (au sens de l'ordre
alphabétique)
- négatif si la chaîne1 est inférieure à la chaîne2
- nul si les chaînes sont identiques.
int strlen(char *chaine)
// renvoie la longueur de la chaine ('\0' non comptabilisé).
int atoi(const char *s) 37
// convertit l'argument s en un int,
Les fonctions de concaténation de chaînes
La fonction strcat
L’appel de strcat se présente ainsi (nous placerons souvent en regard de la
présentation de l’appel d’une fonction le nom du fichier qui en contient le
prototype) :
strcat ( but, source ) (string.h)
Cette fonction recopie la seconde chaîne (source) à la suite de la première
(but), après en avoir effacé le caractère de fin.

38
Les fonctions de concaténation de chaînes
Exemple :
#include <stdio.h>
#include <string.h>
main()
{
char ch1[50] = "bonjour" ;
char * ch2 = " monsieur" ;
printf ("avant : %s\n", ch1) ;
strcat (ch1, ch2) ; Notez la différence entre les deux
printf ("après : %s", ch1) ; déclarations (avec initialisation) de
} chacune des deux chaînes Ch1 et ch2.
La première permet de réserver un
emplacement plus grand que la
constante chaîne qu’on y place
initialement.
RESULTAT
avant : bonjour
après : bonjour monsieur
39
Les fonctions de concaténation de chaînes

La fonction strncat
Cette fonction dont l’appel se présente ainsi :
strncat (but, source, lgmax) (string.h)
travaille de façon semblable à strcat en offrant en outre un contrôle
sur le nombre de caractères qui seront concaténés à la chaîne
d’arrivée (but).

40
Les fonctions de concaténation de chaînes
Exemple : fonction strncat

#include <stdio.h>
#include <string.h>
main()
{
char ch1[50] = "bonjour" ;
char * ch2 = " monsieur" ;
printf ("avant : %s\n", ch1) ;
strncat (ch1, ch2, 6) ;
printf ("après : %s", ch1) ;
}
avant : bonjour
après : bonjour monsi
41
Les fonctions de copie de chaînes
La fonction strcpy
strcpy ( but, source ) (string.h)
recopie la chaîne située à l’adresse source dans l’emplacement
d’adresse destin but. Là encore, il est nécessaire que la taille du
second emplacement soit suffisante pour accueillir la chaîne à recopier,
sous peine d’écrasement intempestif.
Cette fonction fournit comme résultat l’adresse de la chaîne but.

42
Les fonctions de copie de chaînes
La fonction strncpy

strncpy ( but, source, lgmax ) (string.h)

procède de manière analogue à strcpy, en limitant la recopie au


nombre de caractères précisés par l’expression entière lgmax.

Notez bien que, si la longueur de la chaîne source est inférieure à cette


longueur maximale, son caractère de fin (\0) sera effectivement
recopié. Mais, dans le cas contraire, il ne le sera pas.

43
Les fonctions de copie de chaînes
La fonction strncpy
strncpy ( but, source, lgmax )
L’exemple suivant illustre les deux situations :
Fonctions de recopie de chaînes : strcpy et strncpy

#include <stdio.h>
#include <string.h>
main()
{
char ch1[20] = "123456789 10 11 12" ;
char ch2[20] ;
printf (« Donnez un mot : ") ;
gets (ch2) ;
strncpy (ch1, ch2, 6) ;
printf (" ch1 : %s", ch1) ;
}
Donnez un mot : ahmed alioui
ch1 : ahmed 789 10 11 12
44
Les fonctions de comparaison de chaînes
Il est possible de comparer deux chaînes en utilisant l’ordre des
caractères définis par leur code.

La fonction : strcmp ( chaîne1, chaîne2 )

compare deux chaînes dont on lui fournit l’adresse et elle fournit une
valeur entière définie comme étant :
● positive si chaîne1 > chaîne2(c’est-à-dire si chaîne1arrive après
chaîne2, au sens de l’ordre défini par le code des caractères) ;
● nulle si chaîne1 = chaîne2(c’est-à-dire si ces deux chaînes
contiennent exactement la même suite de caractères) ;
● négative si chaîne1 < chaîne2.

45
Les fonctions de comparaison de chaînes
Par exemple (quelle que soit l’implémentation) :

strcmp ("bonjour", "monsieur") est négatif


et :

strcmp ("paris2", "paris10") est positif.

#include <stdio.h>
#include <string.h>
int main () {
char password[] = "123456";
char tmp_password[80];
do {
printf ("Tapez votre mot de passe: ");
gets (tmp_password);
} while (strcmp(password,tmp_password) != 0);
printf ("Bienvenu!");
return 0;
} 46
Les fonctions de comparaison de chaînes

La fonction strncmp :
strncmp ( chaîne1, chaîne2, lgmax )
travaille comme strcmp mais elle limite la comparaison au nombre maximal
de caractères indiqués par l’entier lgmax.

Par exemple :
strncmp ("bonjour", "bon", 4) est positif
tandis que :
strncmp ("bonjour", "bon", 2) vaut zéro.

47
Les fonctions de comparaison de chaînes

Enfin, deux fonctions :


stricmp ( chaîne1, chaîne2 ) (string.h)
strnicmp ( chaîne1, chaîne2, lgmax ) (string.h)

travaillent respectivement comme strcmp et strncmp, mais sans tenir


compte de la différence entre majuscules et minuscules (pour les
seuls caractères alphabétiques)

48
Les fonctions de recherche dans une chaîne

On trouve, en langage C, des fonctions classiques de recherche


de l’occurrence dans une chaîne d’un caractère ou d’une autre
chaîne (nommée alors sous-chaîne).

Elles fournissent comme résultat un pointeur de type char * sur


l’information cherchée en cas de succès, et le pointeur nul dans le
cas contraire.
Voici les principales.
strchr ( chaîne, caractère ) (string.h)
recherche, dans chaîne, la première position où apparaît le
caractère mentionné.

49
Les fonctions de recherche dans une chaîne

 strrchr ( chaîne, caractère ) (string.h)

réalise le même traitement que strchr, mais en explorant la chaîne


concernée à partir de la fin. Elle fournit donc la dernière occurrence
du caractère mentionné.

 strstr ( chaîne, sous-chaîne ) (string.h)

recherche, dans chaîne, la première occurrence complète de la


sous-chaîne mentionnée.

50
La fonction strlen
 La fonction strlen fournit en résultat la longueur
d’une chaîne dont on lui a transmis l’adresse en
argument.
 Cette longueur correspond tout naturellement au
nombre de caractères trouvés depuis l’adresse
indiquée jusqu’au premier caractère de code nul, ce
caractère n’étant pas pris en compte dans la longueur.
Par exemple, l’expression :
strlen ("bonjour")
vaudra 7; de même, avec :
char * adr = "salut" ;
l’expression :
strlen (adr)
vaudra 5.
51
Les fonctions de conversion
Conversion d’une chaîne en valeurs numériques

Il existe trois fonctions permettant de convertir une chaîne de


caractères en une valeur numérique de type int, long ou double.

Ces fonctions ignorent les éventuels espaces de début de chaîne


et, à l’image de ce que font les codes de format %d, %ld et %f, utilisent
les caractères suivants pour fabriquer une valeur numérique.
Le premier caractère invalide arrête l’exploration.

En revanche, ici, si aucun caractère n’est exploitable, ces fonctions


fournissent un résultat nul.

atoi ( chaîne ) (stdlib.h)


fournit un résultat de type int.
atol ( chaîne ) (stdlib.h)
fournit un résultat de type long.
atof ( chaîne ) (stdlib.h)
fournit un résultat de type double. 52
Les fonctions de conversion

Notez que ces fonctions effectuent le même travail que sscanf


appliquée à une seule variable, avec le code de format approprié.

Par exemple (si n est de type int et adr de type char *) :


n = atoi (adr) ;
fait la même chose que :
sscanf (adr, "%d", &n) ;

53
Les fonctions de conversion
Conversion de valeurs numériques en chaîne
La norme ne prévoit pas de fonctions de conversion d’une valeur
numérique en chaîne, c’est-à-dire de fonctions jouant le rôle symétrique
des fonctions atoi, atol, et atof.
En revanche, elle prévoit une fonction sprintf, symétrique de sscanf.
Elle permet de convertir en chaîne une succession de valeurs
numériques, en y incorporant, le cas échéant, d’autres caractères.

Par exemple, si n, de type int, contient 15 et si p, de type float,


contient 785.35 et si tab est un tableau de caractères de taille
suffisante, l’instruction suivante :
sprintf (tab, "%d articles coutent %f8.2 F", n, p) ;

placera dans tab, la chaîne suivante (elle sera bien terminée par un
caractère \0) :

15 articles coutent 785.35 F


54
sizeof
void main()
{
int i;
char c;
caractère : 1
float f;
entier : 2 ou 4
double d;
réel : 4
printf (‘’caractère : %d \n ‘’, sizeof( c));
double : 8
printf (‘’entier : %d \n ‘’, sizeof (i));
printf (‘’réel : %d \n ‘’, sizeof(f));
printf (‘’double : %d \n ‘’, sizeof (d));
}

55
Exercice
Écrire un programme qui lit un verbe du premier groupe (se
termine avec "er") au clavier et qui affiche la conjugaison au
présent de l'indicatif de ce verbe.
Contrôlez s'il s'agit bien d'un verbe qui se termine avec "er"
avant de conjuguer.

56

S-ar putea să vă placă și