Question

lors de la déclaration du tableau à deux dimensions

int random[height][width];

puis l’utiliser dans une fonction

void populate(int random[height][width], int x, int y)

donne le type d'erreur de taille variable déclaré en dehors de toute fonction. Je sais que je fais quelque chose de mal et que c'est quelque chose de petit. J'ai juste une mauvaise mémoire ...

Était-ce utile?

La solution

Je vais maintenant intervenir et vous dire que les tableaux multidimensionnels ne valent pas l'effort cérébral en C ou C ++. Vous ferez bien mieux d'utiliser des tableaux unidimensionnels (ou, mieux encore, des conteneurs standard) et d'écrire une fonction d'indexation:

inline int index (int x, int y)
{
  return x + y * width;
}

Maintenant pour votre problème. C ++ ne prend pas en charge les tableaux de longueur variable C99. Le compilateur doit connaître, au moment de la compilation, la taille du tableau. Ce qui suit, par exemple, ne fonctionnera pas.

int dim = 4;
int ar[dim];

Si dim était const , cela fonctionnerait car le compilateur serait capable de dire exactement quelle largeur ar devrait être (car la valeur dim ne changerait pas). C’est probablement le problème que vous rencontrez.

Si vous voulez pouvoir modifier la taille au moment de la compilation, vous devrez faire quelque chose de plus difficile, comme écrire une référence basée sur un modèle. Vous ne pouvez pas utiliser un pointeur pour des tableaux multidimensionnels en raison de la manière dont ils sont présentés en C / C ++. Un exemple basé sur un modèle pourrait ressembler à l'aberration suivante:

template <int Width, int Height>
void populate(int (&(&random)[Width])[Height], int x, int y);

C'est moche.

Pour l'exécution, vous devez utiliser new pour allouer des données ou utiliser un type de conteneur.

Autres conseils

Vous ne pouvez pas définir le tableau avec des dimensions non constantes (largeur, hauteur) en dehors de la fonction, c'est-à-dire pas dans le cadre de la pile, car les dimensions ne sont pas connues au moment de la compilation. Vous devez utiliser des constantes ou l’allouer dynamiquement (dans le tas ou dans le cadre de la pile).

Lorsqu'un tableau est passé directement en tant que paramètre à une fonction (passage par valeur), il se décompose en un pointeur sur le premier élément du tableau. Même si vous pouvez clairement lire dans la signature les dimensions du tableau, celles-ci sont ignorées par le compilateur. Ce comportement est compatible avec C.

En utilisant C ++, vous pouvez passer le tableau par référence, ce qui ne poserait plus aucun problème.

int extract_value( int (&a)[10][10], int row, int col ) {
   return a[row][col];
}
int main() {
   int a[10][10] = {};
   a[5][5] = 1;
   std::cout << extract_value( a, 5, 5 ) << std::endl;
   int b[5][5];
//   extract_value( b, 2, 2 ); // error: the function takes an array of 10x10
}

Le paramètre de fonction doit correspondre exactement, c'est-à-dire qu'il ne prend qu'un tableau d'éléments 10x10. Vous pouvez vous débarrasser de cette restriction en modélisant la fonction sur la taille des tableaux. Une fois que vous y êtes aussi, tapez:

template <typename T, int Rows, int Cols>
T extract_value( T (&a)[Rows][Cols], int row, int col ) {
   return a[row][col];
}
int main() {
   int a[5][7] = {};
   extract_value( a, 3, 4 );
   int b[8][2] = {};
   extract_value( b, 7, 1 ); // correct, the compiler matches sizes
   double c[4][4] = {};
   extract_value( c, 2, 2 ); // different types are allowed
}

Cette solution est toujours lourde en ce sens que les tailles doivent être des constantes de compilation et que le tableau doit être alloué par pile. La solution consiste à définir une classe prenant la mémoire dynamique dans un tampon (linéaire) et convertissant le système de coordonnées N en un tableau à une dimension pour obtenir des valeurs, comme suggéré précédemment. Vous pouvez obtenir des conseils sur la manière de procéder dans cette FAQ sur la surcharge des opérateurs fournissant une implémentation d'une matrice 2D. Une fois que vous avez cela implémenté, vous pouvez simplement l'utiliser comme paramètre pour les fonctions / méthodes.

Ma recommandation serait de suivre ce dernier chemin: encapsuler le tableau à N dimensions dans une classe qui fournit des conversions en un vecteur 1D (la lite FAQ C ++ utilise un pointeur brut, je préfère les conteneurs STL).

Je vais illustrer avec un exemple:

// globals

const int ARRAY_SIZE = 16 struct ArrayType_t arrayType [ARRAY_SIZE];

Même si ARRAY_SIZE est déclaré constant, sa valeur n’est pas initialisée à la compilation et le compilateur ne connaît donc pas la taille du tableau et génère une telle erreur. Cependant, si vous faites cela comme un hachage, définissez #define ARRAY_SIZE 16 struct ArrayType_t arrayType [ARRAY_SIZE] === > cela fonctionne car ARRAY_SIZE est défini à au moment de la compilation et le compilateur peut connaître la taille du tableau au moment de la compilation.

Vous pouvez utiliser quelque chose comme ceci:

void populate(int height, int width, int **random)
{
    //here you can work from random[0][0] to random[height][width]
}

alors vous pouvez l'utiliser comme ceci:

int main()
{
    int height=10;
    int width=20;
    int **myarray = new int*[height];
    for( int i=0; i< height; i++ ) myarray[i] = new int[width];
    populate( height, width, myarray);
}

mais, bien sûr, vous devrez faire attention aux débordements de mémoire tampon

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top