Pregunta

al declarar la matriz bidimensional

int random[height][width];

y luego usarlo en una función

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

da el error tipo de tamaño variable declarado fuera de cualquier función. Sé que estoy haciendo algo mal, y que es algo pequeño. Solo tengo mala memoria ...

¿Fue útil?

Solución

Voy a intensificar ahora y decirles que los arreglos multidimensionales no valen la pena el esfuerzo del cerebro en C o C ++. Es mucho mejor usar matrices unidimensionales (o, mejor aún, contenedores estándar) y escribir una función de indexación:

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

Ahora para tu problema. C ++ no admite matrices de longitud variable C99. El compilador debe saber, en tiempo de compilación, el tamaño de la matriz. Lo siguiente, por ejemplo, no funcionará.

int dim = 4;
int ar[dim];

Si dim fuera const , funcionaría porque el compilador podría decir exactamente qué tan ancho debería ser ar (porque el valor de dim no cambiaría). Este es probablemente el problema que estás encontrando.

Si desea poder cambiar el tamaño en tiempo de compilación, deberá hacer algo más difícil, como escribir una referencia con plantilla. No puede usar un puntero para matrices multidimensionales debido a la forma en que se presentan en C / C ++. Un ejemplo con plantilla podría parecerse a la siguiente aberración:

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

Esto es feo.

Para el tiempo de ejecución, deberá usar new para asignar datos, o usar un tipo de contenedor.

Otros consejos

No puede definir la matriz con dimensiones no constantes (ancho, alto) fuera de la función, es decir, no en el marco de la pila, porque las dimensiones no se conocen en tiempo de compilación. Debería usar constantes o asignarlas dinámicamente (ya sea en el montón o en el marco de la pila).

Cuando una matriz se pasa directamente como parámetro a una función (pasar por valor), se desintegra en un puntero al primer elemento de la matriz. Incluso si puede leer claramente en la firma las dimensiones de la matriz, el compilador ignora esas dimensiones. Ese comportamiento es compatible con C.

Usando C ++ puede pasar la matriz por referencia y eso ya no sería 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
}

El parámetro de la función debe coincidir exactamente, es decir, solo toma una matriz de 10x10 elementos. Puede deshacerse de esa restricción creando plantillas en los tamaños de matriz. Una vez que esté allí, también escriba:

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
}

Esta solución sigue siendo engorrosa porque los tamaños deben ser constantes de tiempo de compilación y la matriz debe estar asignada en pila. La solución a esto es definir alguna clase que tome memoria dinámica en un búfer (lineal) y tenga una conversión del sistema de coordenadas N en la matriz unidimensional para obtener valores, como se sugirió anteriormente. Puede obtener algunos consejos sobre cómo hacerlo en este Preguntas frecuentes sobre la sobrecarga del operador que proporciona una implementación de una matriz 2D. Una vez que lo haya implementado, puede usarlo como parámetro para funciones / métodos.

Mi recomendación sería seguir este último camino: encapsular la matriz N-dimensional en una clase que proporcione conversiones en un vector 1D (el C ++ FAQ lite utiliza un puntero sin formato, prefiero los contenedores STL).

Ilustraré con un ejemplo:

// globales

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

Aunque ARRAY_SIZE se declara como constante int, su valor no se inicializa en el momento de la compilación y, por lo tanto, el compilador no conoce el tamaño de la matriz y está dando tal error. Sin embargo, si lo hace como un hash, defina #define ARRAY_SIZE 16 struct ArrayType_t arrayType [ARRAY_SIZE] === > esto funciona porque ARRAY_SIZE se define en el tiempo de compilación y el compilador pueden conocer el tamaño de la matriz en tiempo de compilación.

Puedes usar algo como esto:

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

entonces puedes usarlo así:

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

pero, por supuesto, tendrá que estar atento a los desbordamientos del búfer

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top