Domanda

quando si dichiara l'array bidimensionale

int random[height][width];

e quindi usandolo in una funzione

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

indica il tipo di dimensione variabile dell'errore dichiarato al di fuori di qualsiasi funzione. So che sto facendo qualcosa di sbagliato, e che è qualcosa di piccolo. Ho solo un brutto ricordo ...

È stato utile?

Soluzione

Adesso intensificherò e ti dirò che gli array multidimensionali non valgono lo sforzo del cervello in C o C ++. Stai molto meglio usando array monodimensionali (o, meglio ancora, contenitori standard) e scrivendo una funzione di indicizzazione:

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

Ora per il tuo problema. C ++ non supporta matrici a lunghezza variabile C99. Il compilatore deve conoscere, al momento della compilazione, le dimensioni dell'array. Quanto segue, ad esempio, non funzionerà.

int dim = 4;
int ar[dim];

Se dim fosse const , funzionerebbe perché il compilatore sarebbe in grado di dire esattamente quanto ar dovrebbe essere (perché il valore di dim non cambierebbe). Questo è probabilmente il problema che stai riscontrando.

Se vuoi essere in grado di cambiare la dimensione in fase di compilazione, dovrai fare qualcosa di più difficile, come scrivere un riferimento a un modello. Non è possibile utilizzare un puntatore per array multidimensionali a causa del modo in cui sono disposti in C / C ++. Un esempio di modello potrebbe apparire come la seguente aberrazione:

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

Questo è brutto.

Per il runtime, dovrai utilizzare new per allocare i dati o utilizzare un tipo di contenitore.

Altri suggerimenti

Non è possibile definire l'array con dimensioni non costanti (larghezza, altezza) al di fuori della funzione, ovvero non nel frame dello stack, poiché le dimensioni non sono note al momento della compilazione. Dovresti usare le costanti o assegnarle in modo dinamico (sia in heap che nel frame dello stack).

Quando un array viene passato direttamente come parametro a una funzione (passa per valore), decade in un puntatore al primo elemento dell'array. Anche se nella firma è possibile leggere chiaramente le dimensioni dell'array, tali dimensioni vengono ignorate dal compilatore. Tale comportamento è compatibile con C.

Usando C ++ puoi passare l'array per riferimento e questo non sarebbe più un problema.

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
}

Il parametro della funzione deve corrispondere esattamente, ovvero richiede solo un array di 10x10 elementi. È possibile eliminare tale restrizione modellando la funzione sulle dimensioni dell'array. Una volta che ci sei anche il tipo:

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
}

Questa soluzione è ancora ingombrante in quanto le dimensioni devono essere costanti di tempo di compilazione e l'array deve essere allocato in pila. La soluzione a questo sta definendo una classe che prende la memoria dinamica in un buffer (lineare) e ha una conversione dal sistema di coordinate N nell'array monodimensionale per ottenere valori, come era stato suggerito in precedenza. Puoi ottenere alcuni suggerimenti su come farlo in questo FAQ sul sovraccarico dell'operatore che fornisce un'implementazione di una matrice 2D. Dopo averlo implementato, puoi semplicemente usarlo come parametro per funzioni / metodi.

La mia raccomandazione sarebbe quella di seguire quest'ultimo percorso: incapsulare l'array N-dimensionale in una classe che fornisce conversioni in un vettore 1D (la FAQ di C ++ usa un puntatore non elaborato, preferisco i contenitori STL).

Illustrerò con un esempio:

// globali

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

Anche se ARRAY_SIZE è dichiarato come costante int, il suo valore non è inizializzato al momento della compilazione e quindi il compilatore non conosce la dimensione dell'array e sta dando un tale errore. Tuttavia, se lo fai come definito da un hash #define ARRAY_SIZE 16 struct ArrayType_t arrayType [ARRAY_SIZE] === > funziona perché ARRAY_SIZE è definito in tempo di compilazione e compilatore in grado di conoscere la dimensione dell'array al momento della compilazione.

Puoi usare qualcosa del genere:

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

quindi puoi usarlo in questo modo:

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);
}

ma, ovviamente, dovrai fare attenzione agli overflow del buffer

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top