2009-07-05 9 views
23

¿Existe una matriz dentada en C o C++?¿Existen matrices irregulares en C/C++?

Cuando compilo esto:

int jagged[][] = { {0,1}, {1,2,3} }; 

consigo este error:

error: declaration of `jagged' as multidimensional array must have bounds for all dimensions except the first

Respuesta

14

Si lo que desea es su inicialización, se puede decir:

int jagged[][3] = { {0,1}, {1,2,3} }; 

pero la matriz todavía tendrá la forma [2] [3]. Si quieres una matriz dentada verdadera, tendrás que crearla dinámicamente. Y si lo hace, y está usando C++, debería usar un std::vector, como sugiere friol.

12

En C++ (no compilado, y probablemente hay una sintaxis más compacta):

std::vector<std::vector<int> > myArray; 

myArray.push_back(std::vector<int>()); 
myArray.push_back(std::vector<int>()); 

myArray[0].push_back(0); 
myArray[0].push_back(1); 

myArray[1].push_back(1); 
myArray[1].push_back(2); 
myArray[1].push_back(3); 

Así que ahora se puede acceder a los elementos con, por ejemplo, myArray [0] [0], etc.

+1

Erm está presionando un puntero en un vector que no contiene punteros ... – Goz

21

En CI utilizaría una serie de punteros.

Por ejemplo:

int *jagged[5]; 

jagged[0] = malloc(sizeof(int) * 10); 
jagged[1] = malloc(sizeof(int) * 3); 

, etc, etc

+0

En este ejemplo, ¿cuál es la forma correcta de liberar la memoria? – papgeo

15

Hay un montón de maneras de hacerlo. Aquí hay otra manera:

int jagged_row0[] = {0,1}; 
int jagged_row1[] = {1,2,3}; 
int *jagged[] = { jagged_row0, jagged_row1 }; 
+3

+1. Aquí es donde se muestran los literales compuestos de C99: 'int * jagged [] = {(int []) {0,1}, (int []) {1, 2, 3}};' ¿no es muy agradable también? –

+2

El problema con esta solución es que las sub-matrices decaen inmediatamente en punteros, por lo que no tiene forma de decir cuáles son los límites. –

+0

@Neil, no pensé en esto en absoluto. Por supuesto que tienes razón Buen punto :) –

2

En C99 puede hacer lo siguiente:

int jagged_row0[] = {0,1}; 
int jagged_row1[] = {1,2,3}; 

int (*jagged[])[] = { &jagged_row0, &jagged_row1 }; // note the ampersand 

// also since compound literals are lvalues ... 
int (*jagged2[])[] = { &(int[]){0,1}, &(int[]){1,2,3} }; 

La única diferencia aquí (en comparación con la respuesta de rampion) es que las matrices no se deterioran a los punteros y uno tiene para acceder a las matrices individuales a través de otro nivel de direccionamiento indirecto (por ejemplo, *jagged[0]) y se debe registrar el tamaño de cada fila, es decir, sizeof(*jagged[0]) no se compilará), pero son irregulares, apareciendo al hueso;

+0

Pensé que no puedes hacer matrices de tipo incompleto ... oh, estás haciendo una matriz de punteros a un tipo incompleto, eso es posible pero no te compre nada por encima de la respuesta de rampion. –

3

razón por la que recibió el error es que usted m ust especifica los límites para al menos la dimensión externa; es decir

int jagged[][3] = {{0,1},{1,2,3}}; 

No se puede tener dentado [0] ser una matriz de 2 elementos de int e irregular [1] ser una matriz de 3 elementos de int; una matriz de N elementos es un tipo diferente de una matriz de elementos M (donde N! = M), y todos los elementos de una matriz deben ser del mismo tipo.

Lo que puede hacer es lo que los otros han sugerido anteriormente y crear irregulares como una matriz de punteros a int; de esa manera cada elemento puede apuntar a entero matrices de diferentes tamaños:

int row0[] = {0,1}; 
int row1[] = {1,2,3}; 
int *jagged[] = {row0, row1}; 

Aunque row0 y row1 son diferentes tipos (2-elemento arrays vs. 3-elemento de INT), en el contexto de la inicializador que son ambos convertidos implícitamente al mismo tipo (int *).

1

Con C++ 11 listas inicializador this se puede escribir de forma más compacta:

#include <vector> 
#include <iostream> 

int main() { 
    // declare and initialize array 
    std::vector<std::vector<int>> arr = {{1,2,3}, {4,5}}; 
    // print content of array 
    for (auto row : arr) { 
     for (auto col : row) 
      std::cout << col << " "; 
     std::cout << "\n"; 
    } 
} 

la salida es:

$ g++ test.cc -std=c++11 && ./a.out 
1 2 3 
4 5 

para la referencia:

Cuestiones relacionadas