2009-07-05 26 views
23

Czy istnieje coś takiego jak poszarpana tablica w C lub C++?Czy poszarpane tablice istnieją w C/C++?

Kiedy skompilować to:

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

otrzymuję ten błąd:

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

Odpowiedz

14

Jeśli chcesz po prostu go zainicjować, można powiedzieć:

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

ale tablicę nadal będzie miał kształt [2] [3]. Jeśli chcesz mieć prawdziwą tablicę z poszarpanymi liniami, musisz ją utworzyć dynamicznie. A jeśli to zrobisz i korzystasz z C++, powinieneś użyć std::vector, jak sugeruje friol.

12

W C++ (nie skompilowane i prawdopodobnie tam jest bardziej zwarta składnia):

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

Więc teraz można uzyskać dostęp do elementów, na przykład, myArray [0] [0], etc.

+1

Erm przesuwasz wskaźnik do wektora, który nie zawiera wskaźników ... – Goz

21

W CI używałby tablicy wskaźników.

Na przykład:

int *jagged[5]; 

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

itp itd

+0

W tym przykładzie, jaki jest właściwy sposób na zwolnienie pamięci? – papgeo

15

Istnieje kilka sposobów, aby to zrobić. Oto kolejny sposób:

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

+1. To jest tutaj, gdzie literały złożone C99 pokazują: 'int * poszarpane [] = {(int []) {0,1}, (int []) {1, 2, 3}};' czyż nie jest zbyt fajne? –

+2

Kłopot z tym rozwiązaniem polega na tym, że podparary od razu rozpadają się na wskaźniki, więc nie masz możliwości powiedzieć, jakie są granice. –

+0

@Neil, nie myślałem o tym w ogóle. Oczywiście masz rację. Dobra uwaga :) –

2

w C99 można wykonać następujące czynności:

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

Jedyną różnicą (w porównaniu do odpowiedzi zerwa za) jest to, że tablice nie rozpadają się wskaźniki i trzeba aby uzyskać dostęp do poszczególnych tablic poprzez inny poziom pośredni - (np. *jagged[0] - i rozmiar każdego wiersza musi być zapisany - tj. sizeof(*jagged[0]) nie będzie kompilowany) - ale są postrzępione - pojawiające się do kości;)

+0

Myślałem, że nie możesz tworzyć tablic niekompletnego typu ... oh, tworzysz tablicę wskaźników do niekompletnego typu, to jest możliwe, ale nie kupuje ci nic ponad odpowiedź od gracza. –

3

The powodem, dla którego masz błąd, jest to, że ty ustala granice co najmniej w wymiarze zewnętrznym; tj

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

nie może mieć postrzępione [0] będzie tablica 2 element int postrzępione [1] jest tablica 3 element Int; tablica N-element jest innym typem niż tablica M-element (gdzie N! = M), a wszystkie elementy tablicy muszą być tego samego typu.

Co można zrobić z można to, co inni zasugerowali powyżej i utworzyć poszarpane jako tablica wskaźników do int; W ten sposób każdy element może wskazywać liczbę całkowitą tablic o różnych rozmiarach:

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

Chociaż row0 i ROW1 różne typy (2-element tablice w porównaniu z 3-element int), w związku z tym są one inicjatora zarówno niejawnie konwertowane na ten sam typ (int *).

1

z C++ 11 list initializer this można zapisać bardziej zwięźle:

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

Wyjście jest:

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

Dla porównania:

Powiązane problemy