Developpez.com - C
X

Choisissez d'abord la catégorieensuite la rubrique :

next up previous contents index
Next: Tableau et pointeur, c'est Up: Relations entre tableaux et Previous: Exercice

Sous-sections

   
Tableau de pointeurs

Cas général

Pour des raisons de gain de place mémoire, on est parfois amené à créer des tableaux à deux dimensions dont toutes les lignes n'ont pas la même taille. Ceci peut se réaliser à l'aide d'un tableau de pointeurs vers des tableaux de tailles différentes, associé à un autre tableau qui donnera la taille de chaque ligne. On obtient alors la structure de données suivante :


\includegraphics{fig3.eps}

Si nous supposons que le type des objets terminaux est int, pour traduire cette structure de données en langage C, les programmeurs ont l'habitude de << tricher >>, et de ne pas utiliser le type tableau de pointeurs vers des tableaux de int, considéré comme étant trop compliqué (un tel type s'écrit : int (*tab[NB_ELEM])[]). La solution habituellement retenue, consiste à utiliser le type tableau de pointeurs vers des int, soit int *tab[NB_ELEM]. Voici un exemple d'une telle déclaration avec initialisation statique du tableau :

#define NB_ELEM 3
int taille[NB_ELEM] = {1, 2, 3};
int ligne1[] = {10};
int ligne2[] = {20,21};
int ligne3[] = {30,31,32};

int *tab[] = {ligne1, ligne2, ligne3};
Pour une référence à l'élément j de la ligne i, on n'a que l'embarras du choix. Nous donnons ci-après trois méthodes différentes d'imprimer les éléments du tableau ligne par ligne.

Première méthode

On utilise un pointeur vers un entier que l'on fait progresser d'élément en élément dans une ligne :
int i, *p;
for (i = 0; i < NB_ELEM; i++)
   {
   for (p = tab[i]; p < tab[i] + taille[i]; p++)
      printf("%d ",*p);           /*   accès à l'élément courant par *p   */
   printf("\n");
   }

Deuxième méthode

On utilise un pointeur vers le premier élément d'une ligne ; ce pointeur reste fixe.

int i, j, *p;
for (i = 0; i < NB_ELEM; i++)
   {
   for (p = tab[i], j = 0; j < taille[i]; j++)
      printf("%d ",p[j]);         /*   accès à l'élément courant par p[j]   */
   printf("\n");
   }

Troisième méthode

La dernière méthode est surprenante : pour la comprendre, il suffit de remarquer que la variable p dans la seconde solution est inutile, on peut accéder à l'élément courant par la notation tab[i][j].
int i, j, *p;
for (i = 0; i < NB_ELEM; i++)
   {
   for (j = 0; j < taille[i]; j++)
      printf("%d ", tab[i][j]);  /* accès à l'élément courant par tab[i][j] */
   printf("\n");
   }
On remarquera que c'est la même notation que celle qui est utilisée quand on a un vrai tableau à deux dimensions, c'est à dire une structure de données physiquement complètement différente. Que l'accès à deux structures de données différentes puissent se réaliser de la même manière, doit sans doute être considéré comme une faiblesse du langage.

Tableaux de pointeurs vers des chaînes

    C'est pour les tableaux de caractères à deux dimensions, que se manifeste le plus souvent l'intérêt de disposer d'un tableau de lignes de longueurs différentes : les longueurs des chaînes sont extrêmement variables. La aussi, les habitudes sont les mêmes, les programmeurs utilisent le type tableau de pointeurs vers des char 4.1, comme ceci :
char * t[NB_ELEM];
On peut initialiser un tableau de ce type avec des chaînes littérales :
char * mois[] = {"janvier", "février", "mars", "avril", "mai", "juin",
           "juillet", "août", "septembre", "octobre", "novembre", "décembre"};
On remarquera que ceci est impossible avec tout autre type que les char : il est impossible d'écrire :
int * tab[] = {{1}, {2,3}, {4,5,6}};
Une boucle d'impression des valeurs du tableau mois pourra être :
#define NBMOIS 12
int i;

for (i = 0; i < NBMOIS ; i++)
   printf("%s\n",mois[i]);

Paramètres d'un programme

        Les tableaux de pointeurs vers des chaînes de caractères sont une structure de données importante, car c'est sur celle-ci que s'appuie la transmission de paramètres lors de l'exécution d'un programme. Lorsqu'un utilisateur lance l'exécution du programme prog avec les paramètres param1, param2, ... paramn, l'interpréteur de commandes collecte tous ces mots sous forme de chaînes de caractères, crée un tableau de pointeurs vers ces chaînes, et lance la procédure main en lui passant deux paramètres :
-
un entier contenant la taille du tableau ;
-
le tableau de pointeurs vers les chaînes.

Pour que le programme puisse exploiter les paramètres passés par l'utilisateur, la fonction main doit être déclarée de la manière suivante :

int main(int argc, char *argv[])
{
...
}
Les noms argc (pour argument count), ainsi que argv (pour argument values), sont des noms traditionnels, mais peuvent être remplacés par n'importe quels autres noms ;  seuls les types doivent être respectés.

Comme exemple d'utilisation des paramètres, nous donnons le source d'un programme qui imprime son nom et ses paramètres :

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

printf("Nom du programme : %s\n", argv[0]);
for (i = 1; i < argc; i++)
   printf("Paramètre %d : %s\n",i,argv[i]);
}


next up previous contents index
Next: Tableau et pointeur, c'est Up: Relations entre tableaux et Previous: Exercice
Bernard Cassagne
1998-12-09
Contacter le responsable de la rubrique C