2009-07-05 3 views
23

Gibt es so etwas wie ein verzweigtes Array in C oder C++?Gibt es in C/C++ gezackte Arrays?

Wenn ich kompilieren dies:

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

ich diesen Fehler:

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

Antwort

14

Wenn Sie nur um es initialisieren wollen, können Sie sagen:

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

aber das Array wird immer noch die Form [2] [3] haben. Wenn Sie ein echtes gezacktes Array möchten, müssen Sie es dynamisch erstellen. Und wenn Sie das tun, und werden unter Verwendung von C++, sollten Sie eine std::vector verwenden, wie friol vermuten lässt.

12

In C++ (nicht kompiliert, und wahrscheinlich gibt es eine kompaktere Syntax):

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

So, jetzt können Sie die Elemente mit Zugang zum Beispiel arr [0] [0], usw.

+1

Ähm Sie drücken einen Zeiger in einen Vektor, der keine Zeiger enthält ... – Goz

21

In CI würde ein Array von Zeigern verwenden.

Zum Beispiel:

int *jagged[5]; 

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

etc etc.

+0

In diesem Beispiel, was ist der richtige Weg, um den Speicher freizugeben? – papgeo

15

Es gibt eine Reihe von Möglichkeiten, es zu tun. Hier ist eine andere Art und Weise:

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

+1. Dies ist der Punkt, an dem die zusammengesetzten Literale von C99 auftauchen: 'int * gezackt [] = {(int []) {0,1}, (int []) {1, 2, 3}};' Ist das nicht auch schön? –

+2

Das Problem mit dieser Lösung ist, dass die Sub-Arrays sofort zu Zeigern zerfallen, so dass Sie nicht wissen, was die Grenzen sind. –

+0

@Neil, daran habe ich gar nicht gedacht. Natürlich hast du recht. Guter Punkt :) –

2

In C99 können Sie wie folgt vorgehen:

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

Der einzige Unterschied hier (im Vergleich zu rampion Antwort) ist, dass die Arrays zerfallen nicht auf Zeiger und man hat die einzelnen Arrays über einen anderen Dereferenzierungsebene zuzugreifen - (zB *jagged[0] - und die Größe jeder Zeile hat aufgezeichnet werden - dh sizeof(*jagged[0]) nicht kompiliert) - aber sie sind bis auf die Knochen gezackt erscheinende;)

+0

Ich dachte, du kannst keine Arrays von unvollständigem Typ machen ... oh, du machst eine Reihe von Zeigern auf einen unvollständigen Typ, das ist möglich, aber kauft dir nichts über die Antwort von rampion. –

3

die Grund, dass Sie den Fehler haben, ist, dass Sie m Geben Sie die Grenzen für mindestens die äußere Dimension an. d.h.

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

Sie können nicht gezackt haben [0] eine 2-Element-Array von int und gezackten [1] eine 3-Element-Array von int; eine N-Element-Array ist eine andere Art von einer M-Element-Array (wobei N! = M) und alle Elemente eines Arrays müssen vom gleichen Typ sein.

Was Sie können tun, was die anderen oben vorgeschlagen haben und gezackt als ein Array von Zeigern zu int erstellen; Auf diese Weise kann jedes Element verweisen Arrays unterschiedlicher Größe auf ganzzahlige:

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

Obwohl ROW0 und row1 gibt verschiedene Arten (2-Element gegenüber 3-Element-Arrays von int), im Zusammenhang mit der Initialisierer sie beide implizit in den gleichen Typ konvertiert (int *).

1

mit C++ 11 Initialisierer Listen this kann kompakter geschrieben werden:

#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"; 
    } 
} 

Der Ausgang ist:

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

als Referenz: