質問

2次元配列を宣言するとき

int random[height][width];

そしてそれを関数で使用する

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

関数の外部で宣言されたエラー可変サイズ型を提供します。 私は何か間違ったことをしていること、そしてそれが小さいことを知っています。記憶力が悪い...

役に立ちましたか?

解決

今、ステップアップして、多次元配列はCやC ++での脳の努力に値しないことを伝えます。単次元配列(または標準コンテナー)を使用して、インデックス関数を作成する方がはるかに優れています。

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

これで問題が発生しました。 C ++は、C99可変長配列をサポートしていません。コンパイラは、コンパイル時に配列のサイズを知っている必要があります。たとえば、次は機能しません。

int dim = 4;
int ar[dim];

dim const の場合、コンパイラーは ar の幅を正確に知ることができるため、動作します(値のため) dim は変更されません)。これはおそらくあなたが遭遇している問題です。

コンパイル時にサイズを変更できるようにするには、テンプレート化された参照を書くなど、もっと難しいことをする必要があります。 C / C ++でのレイアウト方法のため、多次元配列にポインターを使用することはできません。テンプレート化された例は、次の異常のように見える場合があります。

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

これはいです。

実行時には、 new を使用してデータを割り当てるか、コンテナタイプを使用する必要があります。

他のヒント

関数の外側、つまりスタックフレーム内ではない一定の次元(幅、高さ)で配列を定義することはできません。次元はコンパイル時に不明であるためです。定数を使用するか、動的に割り当てます(ヒープまたはスタックフレームのいずれか)。

配列がパラメーターとして関数に直接渡される場合(値渡し)、配列の最初の要素へのポインターに減衰します。署名で配列の次元を明確に読み取ることができたとしても、それらの次元はコンパイラによって無視されます。この動作はCと互換性があります。

C ++を使用すると、参照によって配列を渡すことができ、それはもう問題にはなりません。

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
}

関数パラメータは正確に一致する必要があります。つまり、10x10要素の配列のみを受け取ります。関数を配列サイズにテンプレート化することにより、その制限を取り除くことができます。また、次のように入力します:

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
}

この解決策は、サイズがコンパイル時定数でなければならず、配列がスタックに割り当てられなければならないという点で、依然として面倒です。これに対する解決策は、以前に提案されたように、バッファ内の動的メモリ(線形)を取得し、値を取得するためにN座標系から1次元配列に変換するクラスを定義することです。こので、その実行方法に関するヒントを入手できます。 2Dマトリックスの実装を提供する演算子のオーバーロードに関するFAQ 。実装したら、それを関数/メソッドのパラメーターとして使用できます。

この最後のパスに従うことをお勧めします:N次元配列を、1Dベクトルへの変換を提供するクラスにカプセル化します(C ++ FAQ liteは生のポインターを使用します。STLコンテナーを好みます)。

例で説明します:

// globals

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

ARRAY_SIZEは定数intとして宣言されていますが、その値はコンパイル時に初期化されないため、コンパイラーは配列のサイズを認識せず、そのようなエラーが発生します。ただし、ハッシュとして定義する場合 #define ARRAY_SIZE 16 struct ArrayType_t arrayType [ARRAY_SIZE] ===&gt; ARRAY_SIZEが定義されているため、これは機能します コンパイル時に、コンパイラはコンパイル時に配列のサイズを知ることができます。

次のようなものを使用できます:

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

次のように使用できます:

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

しかし、もちろん、バッファオーバーフローに注意する必要があります

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top