こんにちは､ ようこそ｡
この講義では､ 多次元配列についてお話したいと思います｡
ここまでで､ 配列といえば､ 多くの種類のデータを格納できる変数と言ったところでしょう｡
もっと複雑になることもある｡
配列は基本的に何次元でも可能です｡
つまり､ これまで説明してきたような線形配列であれば､ それは1次元と呼ばれるものです｡
そして､ 1つの大きさの括弧があるだけなので､
1次元であることがわかります｡
c言語では､ 任意の次元の配列を細かくすることができます｡
つまり､ これはネストされた配列､ 配列の配列のようなものだと考えてください｡
だから､ 2次元配列が最も一般的である｡
しかし､ 実際には3次元配列､ 4次元配列､
5次元配列ができますが､ 3 4 5のユースケースはあまり多くありません｡
本当に､ プログラムで使うのは1次元の配列か､
2次元の配列か､ どちらかです｡
2次元配列は､ 表計算ソフトの行と列を表すもので､
行列や表として視覚化できるため､ 一般的です｡
これは2次元の配列で､ 行と列がありますね｡
そのため､ サイズを指定することで､ 1次元の配列よりも多くのデータを格納することができます｡
でも､ マトリックスのように見えるので､ とても応用が効きます｡
そして､ この行列の概念を持つアプリケーションを書きたいと思うかもしれませんが､
特に数学的なアプリケーションがここでは最も適切でしょう｡
でも､ 2次元配列はいろいろなことに使えますよ｡
一例として､ 行列があります｡
しかし､ もう一度､ テーブルとして可視化してみてください｡
2次元配列は1次元配列と同じように宣言します｡
ただ､ ブラケットをもう1セット用意したことが違います｡
この例では､ 4行5列のint型配列「matrix」を宣言しています｡
つまり､ その2次元配列の中に20個の要素を格納することができるのです｡
そこで､ 各寸法がどのように角括弧の組で指定されるかを知っておく必要があります｡
というように､ 配列が何次元であるかを簡単に見分けることができます｡
そこに3つの括弧があれば､ それは3次元の配列になります｡
4なら4となる｡
こちらは2つあるので2つです｡
そして､ 先の講義までは1つしかなかったので､ それが一次元であることは分かっていました｡
だから､ ブラケットを見る､ そこに注目する｡
今回も4行5列､ 計20個の要素で構成されています｡
2次元配列を初期化するには､ 1次元配列と同じ方法で初期化します｡
同じタイプの構文で､ さらに追加するだけです｡
そのため､ 初期化のために要素をリストアップすると､ 値が行単位でリストアップされることになります｡
そして､ ここでの違いは､ 各行の初期値を入れるときに､
中括弧で囲み､ さらにすべての行を中括弧で囲むことです｡
だから､ こんな感じになるんですね｡
3行4列の2次元の数値配列を作成し､
それを初期化する場合､ 配列全体を中括弧で囲み､
さらに各行ごとに中括弧を入れればよい｡
ここでは､ 0サブ0～10､ 0サブ1～20､ 0サブ2～30､ 0サブ3～40の値を初期化しているわけです｡
多次元配列へのアクセスもそうですね｡
列の行でアクセスするのです｡
0ベースということだけは覚えておいてください｡
つまり､ 左上の1行1列は00で10に相当する｡
1行目2列目は20に相当しますが､ 0以下の数字としてアクセスします｡
最初の配列には3つの行が含まれているので､ 行番号に指定した番号でアクセスし､
次に列番号でアクセスするように指定します｡
しかし､ 個別化はとても簡単で､ コメントで物事を括弧で区切るだけです｡
そしてそれにアクセスすると､ 通常の配列にアクセスするのと同じようにアクセスできますが､
今度は列の中にある行という概念にアクセスすることになります｡
ですから､ 内側の中括弧のペアの使用は実は任意なのですが､ 読みやすさのためには使用したほうがよいでしょう｡
もし中括弧をつけなければ､ 10 20 30
40 15 25 35と連続して記述すればいいのですが､ 何を初期化しているのかが非常にわかりにくくなります｡
プログラマーにとって､ 読みやすさはとても重要です｡ なぜなら､ 読みやすさはコードの質を高め､
コードの保守を容易にするからです｡
この右側を見てみると､ 特にコメントで､ 何を初期化するのか､
どんな値で､ どんな行を初期化するのかを簡単に識別できます｡
それを一行で連番だけにしていたら､ 本当にすぐに分からなくなってしまうんです｡
ですから､ 内側のブラケットは必要ないのですが､ 使ってください｡
1次元配列と同様に､ 配列全体を初期化する必要はありません｡
特定のエリアだけ初期化することも可能です｡
そこで､ この例では､ 4行5列の2次元配列を作成しています｡
各行の最初の3つの要素だけを初期化しています｡
つまり､ 1行目1列目は10､ 1行目2列目は5､ 1行目3列目はマイナス3､
2列目も同様で､ 900 32
31 008となります｡
各行の4番目と5番目の値を設定しなかったものについては､
実際には省略されているので自動的に0に設定されることになります｡
そして､ この場合､ 実際には中括弧､ 内側の中括弧を提供する必要があります｡
なぜなら､ ここでそれをやると､ 初期化がめちゃくちゃになってしまうからです｡
だって､ 中括弧がなかったら､ ただ連続してやるだけですからね｡
つまり､ 最初の12個の要素を初期化することになります｡
つまり､ 1行目のすべての要素､ 2行目のすべての要素､
3行目の最初の2つの要素､ そして3行目の残りの要素､
4行目の残りの要素を0に初期化することになるのです｡
ここでも､ 4行5列の2次元配列となる｡
ただ､ 連続的に行うことになります｡
だから､ もしあなたが特定の初期化要素だけを指定したいのであれば､
中括弧を忘れないでください｡
また､ 指定イニシャライザーも可能です｡
これがC99のコンセプトであることを忘れないでください｡
C11ではオプションで､ 初期化するインデックスを具体的に指定することができるんだ｡
ですから､ 初期化リストに添え字を使うことができます｡ ちょうど1次元の配列のように､
指定された初期化子をやりたい場合は､ 次のようにすればよいのです｡
ここでは4行3列の行列配列を宣言していますが､ 実際には0 0は1に等しく､
1 1は5に等しく､ 2 2は9に等しいと指定されています｡
つまり､ 2 2と言った場合､ 2行目は0から始まるので本当は3行目であり､
2列目は本当は3列目である､ ということです｡
ここでも､ 表やスプレッドシートとして可視化する｡
そして､ 要素へのアクセスは､ 左上から始まります｡
でも､ 4が行を､ 3が列を表していることを理解すれば､
その後は直感的に理解できますね｡
つまり､ 行列の3つの要素を指定された値で初期化しているのです｡
しかし､ ここで注目すべきはその構文だ｡
ここで指定されていない値は､ デフォルトですべて0になります｡
つまり､ これは3つの値だけを初期化することになります｡
初期化する値の各セットは､ 中括弧で囲まれた行の要素になる予定です｡
そして､ 初期化全体は別の中括弧の間に入ります｡
外側の中括弧は通常の初期化と同じで､ 中の配列にアクセスするための括弧があるのがわかると思います｡
そして､ それぞれの行をカンマで区切り､ 行の値の各セットと次のセットをカンマで区切っています｡
そのため､ 値が分離され､ 行インデックスも分離されます｡
今､ 私たちは2つの次元を持っていると言いましたが､
実は他にもいろいろな次元を持つことができるのです｡
2次元でお話ししたことは､ 3次元4次元5次元にも当てはまります｡
つまり､ 3次元の配列を宣言する場合は､
3つの角括弧で宣言することになります｡
ここで､ box という名前の配列は､ int 型で 10 20 30 となります｡
xyzの値を格納するのであれば､
3次元配列を使用した方がいいかもしれませんが､ おそらくこのようなことは必要ないでしょう｡
3次元アレイ以上は本当に少ないですね｡
要約すると､ 1次元配列はデータの行として､
1行､ 2次元配列はテーブルとして行列やスプレッドシート､
3次元配列では､ データテーブルのスタックとして可視化することができますので､
テーブルのスタックです｡
もし､ それだけのデータが必要だとしたら､ アクセスするのは本当に大変だし､
おそらく混乱するでしょうね｡
このプログラムを3次元配列以上でメンテナンスしている人は､
おそらく何が起こっているのか理解するのに迷うでしょう｡
しかし､ もう一度やればいいのです｡ もし､ 1､ 2､ 3次元配列のいずれかを繰り返し処理する必要がある場合は､
おそらくループを使うことになるでしょう｡
そして､ ループの次元が増えれば増えるほど､ ネストしたループが増えることになります｡
つまり､ 3次元の配列を処理する場合､ 3つのネストしたループを持つことになります｡
また､ 4次元の配列を処理する場合､ 4つのネストしたループを持つことになります｡
2次元以上の配列の初期化に関しても､ 同じようなことを適用して､
少し拡張するだけです｡
つまり､ 3次元配列は3レベルの中括弧が入れ子になっており､
内側のレベルには各行の初期化値のセットが含まれているので､
以下のような形になります｡
ここでは､ 3次元の配列､ 2 3 4､ 基本的にはデータテーブルのスタックを用意しています｡
そして､ 最初の3行のブロックは初期化し､
2番目の3行のブロックは初期化することになります｡
つまり､ 3番目と4番目のブロックを初期化せず､ 1番目と2番目のブロックだけを初期化したため､
再び1番目のブロックと2番目のブロックになったということです｡
つまり､ 4つのブロックがあり､ 各ブロックはデータテーブルのスタックと考えることができ､
各ブロックは行と列を持つ｡
ですから､ 最初のブロックは､ 最初の3行だけを初期化することになります｡
そして､ 2番目のブロックは次の3行を初期化しますが､ 3番目と4番目のブロックは初期化しないようにします｡
3つ目と4つ目のブロックを初期化する場合は､
さらに中括弧や中括弧などが出てきます｡
ただし､ 初期化しないものは0に初期化されますが､
同じことです｡
しかしまた､ 非常に面倒なことになり､ しかも非常に難しいことがおわかりいただけると思います｡
次元配列の要素を処理する場合､ ネストしたループを使うことになると述べました｡
ここでも､ 次元の数に直接対応することになります｡
そして､ 各ループは配列の1次元を繰り返し処理することになります｡
だから､ こんな感じになるんですね｡
3次元配列の例です｡
外側のループと､ 内側のループが2つありますね｡
外側のループは最初の外側の配列になるので､ 外側のループは基本的に行を通り､ 2番目は列を通り､
3番目はブロックを通ることになります｡
ここでも注目すべきは､ 「これは本当に毛むくじゃらで面倒なことなんだ」と､
すぐにわかることです｡
ですから､ 3次元4次元の配列はなるべく避け､ 使用例もあまり見かけない､
1次元と2次元が本当に全てです｡
しかし､ 多次元配列は､ より多くのデータを格納し､ 多くのデータ要素で同じ名前にアクセスする方法である､
cの可能性を理解しています｡ ありがとうございます｡