De la même façon qu'un pointeur sur int peut contenir l'adresse d'un nombre isolé ou d'une composante d'un tableau, un pointeur sur char peut pointer sur un caractère isolé ou sur les éléments d'un tableau de caractères. Un pointeur sur char peut en plus contenir l'adresse d'une chaîne de caractères constante et il peut même être initialisé avec une telle adresse.
A la fin de ce chapitre, nous allons anticiper avec un exemple et montrer que les pointeurs sont les éléments indispensables mais effectifs des fonctions en C.
- Pointeurs sur char et chaînes de caractères constantes
Affectation
a) On peut attribuer l'adresse d'une chaîne de caractères constante à un pointeur sur char:
Exemple
char *C; C = "Ceci est une chaîne de caractères constante";
Initialisation
b) Un pointeur sur char peut être initialisé lors de la déclaration si on lui affecte l'adresse d'une chaîne de caractères constante:
char *B = "Bonjour !";
Attention !
Il existe une différence importante entre les deux déclarations:
char A[] = "Bonjour !"; /* un tableau */ char *B = "Bonjour !"; /* un pointeur */
A est un tableau qui a exactement la grandeur pour contenir la chaîne de caractères et la terminaison '\0'. Les caractères de la chaîne peuvent être changés, mais le nom A va toujours pointer sur la même adresse en mémoire.
B est un pointeur qui est initialisé de façon à ce qu'il pointe sur une chaîne de caractères constante stockée quelque part en mémoire. Le pointeur peut être modifié et pointer sur autre chose. La chaîne constante peut être lue, copiée ou affichée, mais pas modifiée.
Exemple
char *A = "Petite chaîne"; char *B = "Deuxième chaîne un peu plus longue"; A = B;
Maintenant A et B pointent sur la même chaîne; la "Petite chaîne" est perdue:
Exemple
char A[45] = "Petite chaîne"; char B[45] = "Deuxième chaîne un peu plus longue"; char C[30]; A = B; /* IMPOSSIBLE -> ERREUR !!! */ C = "Bonjour !"; /* IMPOSSIBLE -> ERREUR !!! */
Pour changer le contenu d'un tableau, nous devons changer les composantes du tableau l'une après l'autre (p.ex. dans une boucle) ou déléguer cette charge à une fonction de <stdio> ou <string>.
Conclusions:
Perspectives et motivation
- Avantages des pointeurs sur char
Comme la fin des chaînes de caractères est marquée par un symbole spécial, nous n'avons pas besoin de connaître la longueur des chaînes de caractères; nous pouvons même laisser de côté les indices d'aide et parcourir les chaînes à l'aide de pointeurs.
Cette façon de procéder est indispensable pour traiter de chaînes de caractères dans des fonctions. En anticipant sur la matière du chapitre 10, nous pouvons ouvrir une petite parenthèse pour illustrer les avantages des pointeurs dans la définition de fonctions traitant des chaînes de caractères:
Pour fournir un tableau comme paramètre à une fonction, il faut passer l'adresse du tableau à la fonction. Or, les paramètres des fonctions sont des variables locales, que nous pouvons utiliser comme variables d'aide. Bref, une fonction obtenant une chaîne de caractères comme paramètre, dispose d'une copie locale de l'adresse de la chaîne. Cette copie peut remplacer les indices ou les variables d'aide du formalisme tableau.
Discussion d'un exemple
Reprenons l'exemple de la fonction strcpy, qui copie la chaîne CH2 vers CH1. Les deux chaînes sont les arguments de la fonction et elles sont déclarées comme pointeurs sur char. La première version de strcpy est écrite entièrement à l'aide du formalisme tableau:
void strcpy(char *CH1, char *CH2) { int I; I=0; while ((CH1[I]=CH2[I]) != '\0') I++; }
Dans une première approche, nous pourrions remplacer simplement la notation tableau[I] par *(tableau + I), ce qui conduirait au programme:
void strcpy(char *CH1, char *CH2) { int I; I=0; while ((*(CH1+I)=*(CH2+I)) != '\0') I++; }
Cette transformation ne nous avance guère, nous avons tout au plus gagné quelques millièmes de secondes lors de la compilation. Un 'véritable' avantage se laisse gagner en calculant directement avec les pointeurs CH1 et CH2 :
void strcpy(char *CH1, char *CH2) { while ((*CH1=*CH2) != '\0') { CH1++; CH2++; } }
Comme nous l'avons déjà constaté dans l'introduction de ce manuel, un vrai professionnel en C escaladerait les 'simplifications' jusqu'à obtenir:
void strcpy(char *CH1, char *CH2) { while (*CH1++ = *CH2++) ; }
Assez 'optimisé' - fermons la parenthèse et familiarisons-nous avec les notations et les manipulations du 'formalisme pointeur' ...
Ecrire un programme qui lit deux tableaux d'entiers A et B et leurs dimensions N et M au clavier et qui ajoute les éléments de B à la fin de A. Utiliser deux pointeurs PA et PB pour le transfer et afficher le tableau résultant A.
Ecrire de deux façons différentes, un programme qui vérifie sans utiliser une fonction de <string>, si une chaîne CH introduite au clavier est un palindrome:
a) en utilisant uniquement le formalisme tableau
b) en utilisant des pointeurs au lieu des indices numériques
Rappel: Un palindrome est un mot qui reste le même qu'on le lise de gauche à droite ou de droite à gauche:
Exemples:
|
PIERRE
|
==>
|
n'est
pas un palindrome
|
OTTO
|
==>
|
est
un palindrome
| |
23432
|
==>
|
est
un palindrome
|
Ecrire un programme qui lit une chaîne de caractères CH et détermine la longueur de la chaîne à l'aide d'un pointeur P. Le programme n'utilisera pas de variables numériques.
Ecrire un programme qui lit une chaîne de caractères CH et détermine le nombre de mots contenus dans la chaîne. Utiliser un pointeur P, une variable logique, la fonction isspace et une variable numérique N qui contiendra le nombre des mots.
Ecrire un programme qui lit une chaîne de caractères CH au clavier et qui compte les occurrences des lettres de l'alphabet en ne distinguant pas les majuscules et les minuscules. Utiliser un tableau ABC de dimension 26 pour mémoriser le résultat et un pointeur PCH pour parcourir la chaîne CH et un pointeur PABC pour parcourir ABC. Afficher seulement le nombre des lettres qui apparaissent au mois une fois dans le texte.
Exemple:
Entrez un ligne de texte (max. 100 caractères) : Jeanne La chaîne "Jeanne" contient : 1 fois la lettre 'A' 2 fois la lettre 'E' 1 fois la lettre 'J' 3 fois la lettre 'N'
Ecrire un programme qui lit un caractère C et une chaîne de caractères CH au clavier. Ensuite toutes les occurrences de C dans CH seront éliminées. Le reste des caractères dans CH sera tassé à l'aide d'un pointeur et de la fonction strcpy.
Ecrire un programme qui lit deux chaînes de caractères CH1 et CH2 au clavier et élimine toutes les lettres de CH1 qui apparaissent aussi dans CH2. Utiliser deux pointeurs P1 et P2, une variable logique TROUVE et la fonction strcpy.
Exemples:
|
Bonjour
|
Bravo
|
==>
|
njou
|
Bonjour
|
bravo
|
==>
|
Bnjou
| |
abacab
|
aa
|
==>
|
bcab
|
Ecrire un programme qui lit deux chaînes de caractères CH1 et CH2 au clavier et supprime la première occurrence de CH2 dans CH1. Utiliser uniquement des pointeurs, une variable logique TROUVE et la fonction strcpy.
Exemples:
|
Alphonse
|
phon
|
==>
|
Alse
|
totalement
|
t
|
==>
|
otalement
| |
abacab
|
aa
|
==>
|
abacab
|