web-dev-qa-db-fra.com

Comment parcourir un tableau de structures

Dans mon application, j'utilise un tableau de structures et il me faut parcourir le tableau. Quelle est la bonne façon de le faire? Comment puis-je vérifier si j'ai atteint la fin du tableau?

// structure
struct MyData {
  int count;
  char name[20];
  float average;
}

J'ai essayé d'itérer comme ça, mais mon application se bloque:

struct MyData data[2] = { {3, "name1", 1.0}, {5, "name2", 2.5} };
struct MyData* ptr = data;

while (*ptr != NULL) {
  // print the contents, works ok for 2 elements

  ptr++; // increment the pointer
}
10
Dariusz

Comment est alloué un tableau de structs

Dans votre cas, le tableau MyData[2] ressemble à ceci en mémoire:

| count | name | average | count | name | average |
^ -- your ptr points here 

Il s’agit d’un espace unique et continu de taille 3 * sizeof (struct MyData).

Chaque fois que vous effectuez une opération ptr++, le pointeur se déplace sur la structure suivante du tableau, ce qui signifie qu'il prend en compte la taille d'un seul struct MyData

| count | name | average | count | name | average |
                         ^ -- after ptr++ your ptr points here

Après un autre ptr++, votre pointeur pointera sur la mémoire juste après votre tableau.

| count | name | average | count | name | average | 
                                                  ^ -- another ptr++ and your ptr points here

Lorsque vous déréférenciez votre pointeur ptr, vous accédez à une mémoire qui n'est pas encore utilisée ni même allouée. Ceci est un comportement indéfini et à cause de cela votre application se bloque.

Comment itérer?

Il y a plusieurs façons de le faire. Notez que tous les moyens ne sont pas applicables dans tous les cas.

Un simple pour

Très souvent, nous connaissons simplement la taille du tableau. Nous pouvons alors simplement utiliser une boucle for normale pour parcourir le contenu.

int len = 2;
struct MyData data[len] = { {3, "name1", 1.0}, {5, "name2", 2.5} };
struct MyData* ptr = data;
for (int i=0; i<2; i++, ptr++ ) {
   // do your thing with the ptr
   // and note that ptr gets increased inside for
}

Utilisation de sizeof pour déterminer la longueur d'un tableau

struct MyData data[2] = { {3, "name1", 1.0}, {5, "name2", 2.5} };
struct MyData* ptr = data;
struct MyData* endPtr = data + sizeof(data)/sizeof(data[0]);
while ( ptr < endPtr ){
   // do your thing with the ptr
   ptr++;
}

La sizeof(data)/sizeof(data[0]) calcule la quantité d'éléments: obtient la taille totale d'un tableau et le divise par la taille d'un seul élément. 

Cette méthode a ses inconvénients. Il ne peut pas être utilisé lorsque le tableau est déclaré en tant que pointeur! Par exemple, lorsque nous transmettons le tableau en tant que paramètre à une fonction, il est généralement converti en un pointeur. Nous ne pouvons alors pas déterminer la taille du tableau.

19
Dariusz

Si vous n'avez aucun contrôle sur la taille du tableau et que vous ne pouvez même pas le demander, vous pouvez essayer de réorganiser votre code, en n'utilisant pas un tableau de MyData, mais un tableau de pointeurs à MyData. Votre tableau doit alors être un emplacement plus long pour stocker une garde avec une valeur NULL.

Votre itération ressemblera à celle que vous avez écrite à titre d'exemple.

// N is the number of MyData instances you have
MyData* vData[N+1];
// vData[i] is filled, and vData[N] = NULL

// ...

MyData* vPtr = vData[0];
while(vPtr) {
    // ...
}

Mais cela implique de changer le type de votre tableau de MyData[] à MyData*[]. Si vous ne pouvez pas, vous devriez suivre la réponse de Dariusz.

0
Oragon Efreet