4

ここで解決策を探しているわけではありません。Google でたくさん見つけました。説明を探しています。

配列で遊んでいるときに、2D配列を動的に宣言すると期待どおりに機能しないことがわかりました

1D配列、機能

int main()
{
int rows;
int* pointer;
pointer = new int[rows]; 
}

2D 配列、機能しません

int main()
{
int rows;
int columns;
int* pointer;
pointer = new int[rows][columns]; //error on this line
}

これは、通常の配列で行う方法であるため、物事を行う直感的な方法のように思えますが、明らかに正しくなく、コンパイルされません。

これが事実である理由の明確な説明を見つけることができませんでした。うまくいけば、ここの誰かが私を啓発してくれます。

ありがとう :)

4

5 に答える 5

6

これが機能しない理由は、2 次元配列を使用できるようにするには、必要なタイプの多くの配列を指すポインターの 1 つの配列が必要だからです。

この場合、アドレスを int* の配列 (各「セル」は int の配列を指します) に int* 型の変数に格納しようとしています。これは int** である必要があります。

要約すると: 1D 配列: int* 2D 配列: int** 3D 配列: int***

すべての配列が 1 次元でなければならない理由は、メモリが 1 次元であるため (すべてのメモリをメモリ アドレスの 1 つの大きな配列と考えてください)、多次元配列を「偽造」する必要があることを意味します。

于 2012-09-13T05:03:11.043 に答える
4

これは、他の回答で説明されているデータ型の問題だけではありません。

のような構文

pointer = new int[rows][columns]

columnsが定数式の場合にのみ有効です。そこで変数を使用することはできません (ただし、変数にrowsなる可能性があることに注意してください)。

これが説明です。C++ 標準では、次の方法でのみ、演算子で 2 次元配列構文を使用できますnew(§5.3.4/1 から)。

new-expression:
  ::opt new new-placementopt new-type-id new-initializeropt
  ::opt new new-placementopt ( type-id ) new-initializeropt
new-placement:
  ( expression-list )
new-type-id:
  type-specifier-seq new-declaratoropt
new-declarator:
  ptr-operator new-declaratoropt
  noptr-new-declarator
noptr-new-declarator:
  [ expression ] attribute-specifier-seqopt
  noptr-new-declarator [ constant-expression ] attribute-specifier-seqopt
new-initializer:
  ( expression-listopt )
  braced-init-list

関連する部分は次のとおりです。

noptr-new-declarator:
  [ expression ] attribute-specifier-seqopt
  noptr-new-declarator [ constant-expression ] attribute-specifier-seqopt

最初の行は、type-id の後に括弧で囲まれたを 1 つ含めることができることを意味します。2 行目 (再帰ステートメント) では、最初の括弧の後に複数の括弧のペアを使用できますが、定数式を囲む必要があります。

標準はこれをさらに説明します(強調鉱山):

(§5.3.4/5) 割り当てられたオブジェクトが配列の場合 (つまり、noptr-new-declarator 構文が使用されているか、new-type-id または type-id が配列型を示している)、new-expression は以下を生成します。配列の最初の要素 (存在する場合) へのポインター。[注: new int と new int[10] の型はどちらも int* で、 new int[i][10] の型は int (*)[10]です。 new-declarator は、関連する配列型に属します。

(§5.3.4/6) noptr-new-declarator 内のすべての定数式は整数定数式 (5.19) であり、厳密に正の値に評価されます。noptr-new-declarator の式は、整数型、スコープなし列挙型、または整数型またはスコープなし列挙型への単一の非明示的な変換関数が存在するクラス型 (12.3) でなければなりません。[...] [ 例:定義 int n = 42 を考えると、new float[n][5] は整形式 (n は noptr-new-declarator の式であるため) ですが、new float[5][ n] は形式が正しくありません (n は定数式ではないため)。— 終了例 ]

于 2012-09-13T05:15:59.047 に答える
3

次のように理解できます。

2 次元配列は、人間が表現するための行と列を持つグリッドのように見えますが、メモリ内では連続したメモリに格納されます。したがって、2 次元配列またはサイズと言うときはいつでも、それぞれが次々に格納される要素の配列mxnについて話していることになります。つまり、3x3 グリッド要素は次のように保存されます。mn

(0,0) (0,1) (0,2) (1,0) (1,1) (1,2) (2,0) (2,1) (2,2)

そのようなデータ構造にアクセスしたい場合は、ポインタへのポインタ、つまりすべての行の最初の要素の位置のアドレスの配列へのポインタを使用する必要があります。

したがって、配列は3(行数)のアドレスでアクセスできます

(Address of element 0,1) (Address of element 1,0) (Address of element 2,0)

要素のアドレスが格納されているため、このポインターの配列にアクセスするには、ポインターへのポインターが必要です (すべての行の最初の要素のアドレスを保持します)。

1D 配列の場合:

int* pointer = new int[3];

Array: (0) (1) (2)
pointer: (Address of first element of Array)

2D 配列の場合:

int **pointer = new int[3][3];

Array: (0,0) (0,1) (0,2) (1,0) (1,1) (1,2) (2,0) (2,1) (2,2)
Row Address Array: (Address of 0,1) (Address of 1,0) (Address of 2,0)
pointer: (Address of first element of Row Address Array)

お役に立てれば!

于 2012-09-13T05:00:48.383 に答える
0

他の人がよく説明していますが、動的にサイズ変更された多次元配列を使用して作成することに光を当てる例を次に示しますnew

int rows = 20;
int columns = 30;

// the following is essentially just an array of int pointers
int **pointer = new int*[rows]; 

// so, loop through the array creating the second dimension
for (int i = 0;i < rows;i++)
    pointer[i] = new int[columns];
于 2012-09-13T05:13:03.520 に答える
0

これは 1 次元の char ポインター配列ですchar* Dynamic_One_Dimensional_Char_Pointer_Array。に注意してchar *ください。

これは 2 次元の char ポインター配列ですchar **Dynamic_Two_Dimensional_Char_Pointer_Array。に注意してchar **ください。

これは、2 次元の char ポインタ配列にメモリを割り当てる方法です。

    //memory allocated for elements of rows.
    Dynamic_Two_Dimensional_Char_Pointer_Array = new char *[ROWS] ;

    //memory allocated for  elements of each column.
    for(   i = 0 ; i < ROWS ; i++ ) Dynamic_Two_Dimensional_Char_Pointer_Array[i] = new char[COLUMNS];

[rows][columns]これは、2D 配列 ( )を印刷する方法です。

   for(rows=0;rows<maxLines;rows++)
   {
       for(int columns=0;columns<strlen(Dynamic_Two_Dimensional_Char_Pointer_Array[rows]);columns++)
       {
            cout<<Dynamic_Two_Dimensional_Char_Pointer_Array[rows][columns]<<"";
       }
       cout<<"  \n";
   }

これは、2 次元の char ポインター配列のメモリの割り当てを解除する方法です。

//free the allocated memory
for(   i = 0 ; i < ROWS ; i++ )   delete [] Dynamic_Two_Dimensional_Char_Pointer_Array[i] ;
delete [] Dynamic_Two_Dimensional_Char_Pointer_Array ;

完全なサンプル コード:

#include<vector>
#include<string>
#include<iostream>
using namespace std;

int main()
{

    int COLUMNS =80; //80 characters wide
    int ROWS =20;// 20 lines
    int i,maxLines=0;

    char* Dynamic_One_Dimensional_Char_Pointer_Array = new char[80];
    char **Dynamic_Two_Dimensional_Char_Pointer_Array = 0;

    //memory allocated for elements of rows.
    Dynamic_Two_Dimensional_Char_Pointer_Array = new char *[ROWS] ;

    //memory allocated for  elements of each column.
    for(   i = 0 ; i < ROWS ; i++ ) Dynamic_Two_Dimensional_Char_Pointer_Array[i] = new char[COLUMNS];


    strcpy(Dynamic_One_Dimensional_Char_Pointer_Array,"apples 123 oranges 456 bananas 789 lemons 101112 kiwi 132415 grapes 161718" );
    cout<<"  \ninput = "<<Dynamic_One_Dimensional_Char_Pointer_Array<<"  \n\n";
    cout<<"Output = \n";

    char seperators[]   = " ,\t\n";
    char *token; 
   token = strtok( Dynamic_One_Dimensional_Char_Pointer_Array, seperators );  
   i=0;

   while( token != NULL )
   {
      strcpy(Dynamic_Two_Dimensional_Char_Pointer_Array[i],token);
      token = strtok( NULL, seperators );  
      i++;
   }
   maxLines=i;
   cout<<"  \n";

   cout<<"show contents 1 print [rows] \n";
   cout<<"-------------------------------------------\n";
   for(int rows=0;rows<maxLines;rows++)
   {
     cout<<Dynamic_Two_Dimensional_Char_Pointer_Array[rows]<<"  \n";
   }
   cout<<"  \n";

   cout<<"show contents 2  print [rows][columns]\n";
   cout<<"-------------------------------------------\n";

   for(rows=0;rows<maxLines;rows++)
   {
     //cout<<Dynamic_Two_Dimensional_Char_Pointer_Array[rows]<<"  \n";
       for(int columns=0;columns<strlen(Dynamic_Two_Dimensional_Char_Pointer_Array[rows]);columns++)
       {
            cout<<Dynamic_Two_Dimensional_Char_Pointer_Array[rows][columns]<<"";
       }
       cout<<"  \n";
   }



    delete[] Dynamic_One_Dimensional_Char_Pointer_Array;

    //free the allocated memory
    for(   i = 0 ; i < ROWS ; i++ )   delete [] Dynamic_Two_Dimensional_Char_Pointer_Array[i] ;
    delete [] Dynamic_Two_Dimensional_Char_Pointer_Array ;

    return 0;
}
于 2012-09-13T05:58:58.340 に答える