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
}
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.
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.
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.