CやC++でギザギザの配列のようなものはありますか?
これをコンパイルすると:
int jagged[][] = { {0,1}, {1,2,3} };
このエラーが発生します:
エラー:多次元配列としての「ギザギザ」の宣言には、最初の次元を除くすべての次元の境界が必要です
Cでは、ポインターの配列を使用します。
例えば:
int *jagged[5];
jagged[0] = malloc(sizeof(int) * 10);
jagged[1] = malloc(sizeof(int) * 3);
などなど。
それを行う方法はたくさんあります。別の方法は次のとおりです。
int jagged_row0[] = {0,1};
int jagged_row1[] = {1,2,3};
int *jagged[] = { jagged_row0, jagged_row1 };
初期化するだけの場合は、次のように言うことができます。
int jagged[][3] = { {0,1}, {1,2,3} };
ただし、配列の形状は[2] [3]のままです。真のギザギザの配列が必要な場合は、動的に作成する必要があります。そして、それを行い、C++を使用している場合は、friolが示唆しているように、std::vector
を使用する必要があります。
C++(コンパイルされておらず、おそらくよりコンパクトな構文があります):
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);
これで、たとえばmyArray [0] [0]などを使用して要素にアクセスできるようになりました。
C99では、次のことができます。
_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} };
_
ここでの唯一の違い(ランピオンの答えと比較して)は、配列がポインターに減衰せず、別のレベルの間接参照を介して個々の配列にアクセスする必要があることです-(例:_*jagged[0]
_-そして各行のサイズは記録される-つまり、sizeof(*jagged[0])
はコンパイルされません)-しかし、それらはギザギザになっています-骨に表示されます;)
エラーが発生した理由は、少なくとも外側の寸法の境界を指定する必要があるためです。つまり.
int jagged[][3] = {{0,1},{1,2,3}};
Jagged [0]をintの2要素配列にし、jagged [1]をintの3要素配列にすることはできません。 N要素配列はM要素配列(N!= M)とは異なる型であり、配列のすべての要素は同じ型である必要があります。
あなたがすることcanは、他の人が上で提案したことであり、intへのポインタの配列としてギザギザを作成します。そうすれば、各要素は異なるサイズの整数配列を指すことができます。
int row0[] = {0,1};
int row1[] = {1,2,3};
int *jagged[] = {row0, row1};
Row0とrow1は異なる型(intの2要素配列と3要素配列)ですが、初期化子のコンテキストでは、両方とも暗黙的に同じ型(int *)に変換されます。
C++ 11初期化子リストを使用すると this よりコンパクトに記述できます。
#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";
}
}
出力は次のとおりです。
$ g++ test.cc -std=c++11 && ./a.out
1 2 3
4 5
参考のために:
Cの複合リテラルを使用して、メモリ内で連続している真にギザギザの配列を次のように初期化することもできます。
int (*arr[]) = { (int []) {0, 1}, (int []){ 2, 3, 4}, (int []){5, 6, 7, 8} }
これは、メモリ内で連続して配置されます。