Arduino-multi-dimensional-arrays

提供:Dev Guides
移動先:案内検索

Arduino-多次元配列

2次元の配列(つまり、添字)は、多くの場合、行と列に配置された情報で構成される値のテーブルを表します。

以下は、多次元配列の主要な機能です-

  • 特定のテーブル要素を識別するには、2つの添え字を指定する必要があります。
  • 慣例により、最初は要素の行を識別し、2番目は要素の列を識別します。
  • 特定の要素を識別するために2つの添え字が必要な配列は、2次元配列または2次元配列と呼ばれます。
  • 2次元以上の配列は多次元配列と呼ばれ、3次元以上の配列を持つことができます。

次の図は、2次元配列 a を示しています。 配列には3行4列が含まれているため、3行4列の配列です。 一般に、 m 行と n 列の配列は、* m行n列の配列*と呼ばれます。

多次元配列

配列 a のすべての要素は、 a [i] [j] という形式の要素名で識別されます。 ここで、aは配列の名前で、 ija の各要素を一意に識別する添え字です。 行0の要素の名前はすべて、最初の添え字が0であることに注意してください。列3の要素の名前にはすべて、3番目の添え字があります。

多次元配列は、1次元配列のように宣言で初期化できます。 たとえば、行0の要素に値1と2、行1の要素に値3と4を持つ2次元配列 b は、次のように宣言および初期化できます-

int b[ 2 ][ 2 ] = { { 1, 2 }, { 3, 4 } };

値は中括弧内の行ごとにグループ化されます。 したがって、1と2はそれぞれb [0] [0]とb [0] [1]を初期化し、3と4はそれぞれb [1] [0]とb [1] [1]を初期化します。 特定の行に十分な初期化子がない場合、その行の残りの要素は0に初期化されます。 したがって、次の宣言は、b [0] [0]を1に、b [0] [1]を0に、b [1] [0]を3に、b [1] [1]を4に初期化します。

int b[ 2 ][ 2 ] = { { 1 }, { 3, 4 } };

以下は、宣言での2次元配列の初期化を示す例です。

  • 行a〜cは、それぞれ2行3列の3つの配列を宣言します。
  • array1の宣言(行a)は、2つのサブリストに6つの初期化子を提供します。 最初のサブリストは、配列の行0を値1、2、および3に初期化します。 2番目のサブリストは、配列の行1を値4、5、および6に初期化します。
  • 各サブリストを囲む中括弧がarray1初期化リストから削除されると、コンパイラーは行0の要素を初期化し、その後に行1の要素を初期化して、同じ結果をもたらします。
  • array2の宣言(行 b )は、5つの初期化子のみを提供します。
  • 初期化子は行0に割り当てられ、次に行1に割り当てられます。 明示的な初期化子を持たない要素はゼロに初期化されるため、array2 [1] [2]はゼロに初期化されます。
  • array3の宣言(行 c )は、2つのサブリストで3つの初期化子を提供します。
  • 行0のサブリストは、行0の最初の2つの要素を明示的に1と2に初期化します。 3番目の要素は暗黙的にゼロに初期化されます。
  • 行1のサブリストは、最初の要素を明示的に4に初期化し、最後の2つの要素を暗黙的にゼロに初期化します。
  • プログラムは関数printArrayを呼び出して、各配列の要素を出力します。 関数プロトタイプ(行 k )がパラメーター const int a [] [columns] を指定していることに注意してください。
  • 関数が引数として1次元配列を受け取ると、関数のパラメーターリスト内の配列括弧は空になります。
  • 2次元配列の最初の次元のサイズ(つまり、行数)も必要ありませんが、後続のすべての次元サイズが必要です。 コンパイラはこれらのサイズを使用して、多次元配列の要素のメモリ内の位置を決定します。
  • すべての配列要素は、次元の数に関係なく、メモリに連続して格納されます。 2次元配列では、行0がメモリに格納され、その後に行1が格納されます。

void printArray ( const int [][ 3 ] );//prototype
const int rows = 2;
const int columns = 3;
int array1[ rows ][ columns ] = { { 1, 2, 3 }, { 4, 5, 6 } };
int array2[ rows ][ columns ] = { 1, 2, 3, 4, 5 };
int array3[ rows ][ columns ] = { { 1, 2 }, { 4 } };

void setup () {

}
void loop () {
   Serial.print ("Values in array1 by row are: ") ;
   Serial.print (“\r” ) ;
   printArray(array1) ;
   Serial.print ("Values in array2 by row are: ") ;
   Serial.print (“\r” ) ;
   printArray(array2) ;
   Serial.print ("Values in array3 by row are: ") ;
   Serial.print (“\r” ) ;
   printArray(array3) ;
}

//output array with two rows and three columns

void printArray( const int a[][ columns ] ) {
  //loop through array's rows
   for ( int i = 0; i < rows; ++i ) {
     //loop through columns of current row
      for ( int j = 0; j < columns; ++j )
      Serial.print (a[ i ][ j ] );
      Serial.print (“\r” ) ;//start new line of output
   }
//end outer for
}

//end function printArray

結果

Values in array1 by row are:
1 2 3
4 5 6
Values in array2 by row are:
1 2 3
4 5 0
Values in array3 by row are:
1 2 0
4 0 0

-各行は1次元配列です。 特定の行の要素を見つけるには、関数は各行にある要素の数を正確に知る必要があるため、配列にアクセスするときに適切な数のメモリ位置をスキップできます。 したがって、a [1] [2]にアクセスすると、関数はメモリ内の行0の3つの要素をスキップして行1に到達することを認識しています。 次に、関数はその行の要素2にアクセスします。 多くの一般的な配列操作は FOR ステートメントを使用します。

たとえば、次の FOR ステートメントは、配列 a の行2のすべての要素を設定します。

for ( int column = 0; column < 4; ++column )
   a[ 2 ][ column ] = 0;
*FOR* ステートメントは、2番目の添え字(つまり、列の添え字)のみを変更します。 前述の *FOR* ステートメントは、次の割り当てステートメントと同等です-
a[ 2 ][ 0 ] = 0;
a[ 2 ][ 1 ] = 0;
a[ 2 ][ 2 ] = 0;
a[ 2 ][ 3 ] = 0;

次の*ネストされたFOR ステートメントは、配列 *a 内のすべての要素の合計を決定します-

total = 0;
for ( int row = 0; row < 3; ++row )
for ( int column = 0; column < 4; ++column )
total += a[ row ][ column ];
*FOR* ステートメントは、配列の要素を一度に1行ずつ合計します。 外側の *FOR* ステートメントは、行(行の添字)を0に設定することから始まります。 したがって、行0の要素は、内側の *FOR* ステートメントによって合計されます。

外側の FOR ステートメントは、行を1にインクリメントし、行1の要素を合計できるようにします。 次に、外側の FOR ステートメントが行を2にインクリメントするため、行2の要素を合計できます。 ネストされた FOR ステートメントが終了すると、合計にはすべての配列要素の合計が含まれます。