1. 配列は要素のコンテナだよ
たぶん、パソコンがめっちゃ大量の情報を処理できるって聞いたことあるよね。条件分岐(if-else)やループ(for、while)ももちろん役立つ。でも、それだけじゃ足りない。だって、処理するデータをどこかに保存しないといけないからさ。
そんな時、C#にも他のほとんどのプログラミング言語にもある便利なものが配列(Array)なんだ。テーブルって呼ばれることもあるよ。
配列は、1つの値じゃなくて複数の値を保存できる特別なオブジェクトなんだ。
前に変数を箱に例えたことがあるけど(何か1つの値を保存できる箱)、配列は中が仕切られてる箱みたいな感じ。それぞれの「箱-配列」のセクションには番号がついてる。番号はもちろんゼロから始まるよ…
もう1つ例え話をしよう。普通の一軒家とマンションを比べてみて。一軒家には1つの家族しか住めないけど、マンションは部屋ごとに分かれてる。普通の家に手紙を出すなら、その家の住所だけでOK。でもマンションに住んでる家族に手紙を出すなら、家の住所+部屋番号も必要だよね。
つまり、配列変数はマンションみたいなもの。1つの値じゃなくて複数の値を保存できる。部屋(セル)がいくつもあって、それぞれ番号(インデックス)でアクセスできるんだ。
そのためには、変数名の後ろに角カッコでセルのインデックスを書くだけ。超カンタン!
array[インデックス] = 値;
ここでarrayは配列変数の名前、インデックスは配列内のセル番号、値はそのセルに入れたい値だよ。
でもまずは、配列の作り方から見てみよう。
2. C#で配列を作る
例えば、プログラムで100個の整数をどこかに保存したいとする。たぶん配列がピッタリだよね。じゃあ、どうやって作るの?
もし1つの整数だけ保存したいなら、int型で十分。でも100個の整数を保存したいなら、int型の配列が必要だよ。コードはこんな感じ:
int[] array = new int[100];
このコードを分解してみよう。
もう分かったかもしれないけど、イコールの左側はarrayという名前の変数宣言で、型はint[]。intの後ろに角カッコがついてて、「この型の箱には1つじゃなくて複数の値が入るよ」って感じ。
イコールの右側は「オブジェクトの作成」(newって単語)で、100個のint型のセルを作るって意味。そんなに難しくないよね。
例えば、20個の実数を保存する配列を作りたいなら、コードはこんな感じになる:
double[] vals = new double[20];
配列のセルの数は配列のサイズとか配列の長さって呼ばれる。たくさんの値を保存できるから、配列はコンテナとも呼ばれるよ。
重要なポイント:配列コンテナのサイズは作った後に変えられない。
新しく作り直すことはできるけど、すでに作った配列の長さは変えられないよ。
3. 配列のセルを操作する
よし、配列の作り方は分かった。じゃあ、どうやって使うの?
ほぼ普通の変数と同じだけど、配列変数の名前の後ろに必ずセル番号を書かないといけない。
配列のセル番号は必ずゼロから始まる。10個の配列なら、セル番号(インデックス)は0..9。200個なら0..199。そんな感じ。
例:
int[] a = new int[10]; // 10個のint型配列を作る
a[2] = 4; // インデックス2のセルに4を入れる
a[7] = 9; // インデックス7のセルに9を入れる
a[9] = a[2] + a[5]; // インデックス9のセルに、セル2(4が入ってる)とセル5(0が入ってる)の合計を入れる
このコードを実行した後、メモリにはこんな感じで保存されるよ:
配列の左側の列(グレー)はセルの番号(インデックス)。セルには入れた値:4、9、4が入ってる。配列を作った直後は全部ゼロで埋まってるよ。
重要。配列の全セルは同じデータ型。文字列配列stringを作ったら、セルには文字列しか入れられない。配列の型は作る時に決まる。型も長さも後から変えられないよ。
4. 配列のメモリでの扱い
さっきのイラストはちょっと正確じゃないんだ。
配列(文字列も同じ)を作ると、メモリに2つのブロックが確保される:1つは配列(コンテナ)自体、もう1つはそのアドレスを保存する変数。詳しくは下の図を見てね:
緑色は10個のint型配列と、そのアドレス(参照)を保存するint[]型変数を表してる。
比較のために、青色は普通のint型変数で、値199を保存してる。
なんか文字列のメモリ保存と似てると思わない?
そう、文字列と同じ。配列型の変数同士で代入もできるんだ:
int[] a = new int[10]; // 10個のint型配列を作る
a[2] = 4; // インデックス2のセルに4を入れる
a[7] = 9; // インデックス7のセルに9を入れる
int[] b = a; // bにaのアドレスを保存
// これでaもbも同じ配列オブジェクトを指す
a[9] = b[2] + a[7]; // 配列オブジェクトのインデックス9のセルに、セル2(4)とセル7(9)の合計を入れる
配列オブジェクト自体はそのままで、aとbは同じアドレス(参照)を持つ。イラストを見てみて:
5. 配列をもっと詳しく
配列はどんな型でも作れる。型名の後ろに角カッコをつけるだけ。配列作成の基本形はこう:
型[] 名前 = new 型[数];
ここで型は配列セルの型、名前は変数名、数は配列のセル数だよ。
上の例は基本形:配列変数の宣言と配列オブジェクトの作成。実はこれは別々にやってもOK。
型[] 名前;
名前 = new 型[数];
もう1つ大事なポイント
配列のインデックスやセル数には変数や式も使えるよ。
例:
int n = 100;
int[] a = new int[n]; // n個の配列を作る
int n = 100;
int[] a = new int[n * 2 + 3]; // 203個の配列を作る
int n = 100;
int[] a = new int[n];
a[n-1] = 2; // a[99] = 2;
a[n-2] = 3; // a[98] = 3;
a[n/5] = a[n-1] + a[n-2]; // a[20] = a[99] + a[98];
配列の範囲外アクセス
ちなみに、配列に存在しないインデックス(この場合0..99以外の整数)でアクセスしようとすると、プログラムはIndexOutOfRangeException(配列の範囲外インデックス)エラーで強制終了するよ。
6. 配列の長さ
さっきの例みたいに、配列型の変数だけ作って、後でどこかで配列オブジェクトを代入することもできる。例えばこんな感じ:
int[] array; // int[]型の配列変数を作る
if (a < 10) // もしaが10未満なら
array = new int[10]; // 10個の配列を作る
else // それ以外なら
array = new int[20]; // 20個の配列を作る
じゃあ、こういう配列の要素数を知りたい時はどうする?
配列には特別なプロパティ(変数)がある。それがlength。配列の長さはこうやって取得できる:
array.Length;
arrayは配列変数名、Lengthは配列オブジェクトのプロパティ名。Lengthの値は変更できない。Lengthを他の変数に代入するのはOKだけど、Length自体に値を代入するのはNG(コンパイルエラーになる)。
さっきの例を続けると、こんな感じで使えるよ:
int[] array; // int[]型の配列変数を作る
if (a < 10) // もしaが10未満なら
array = new int[10]; // 10個の配列を作る
else // それ以外なら
array = new int[20]; // 20個の配列を作る
for (int i = 0; i < array.Length; i++) // 配列の全要素をループ:0からarray.Length-1まで
{
Console.WriteLine(array[i]);
}
7. C#の配列に関する事実
配列について知っておくべきことをまとめるよ:
- 事実1. 配列はたくさんのセルでできてる。
- 事実2. 特定のセルにアクセスするには、その番号を指定する。
- 事実3. 全セルは同じ型。
- 事実4. 全セルの初期値は0、null(アドレス型の場合)、false(bool型の場合)。
- 事実5. string[] listは変数宣言だけで、コンテナ(配列オブジェクト)はまだ作られてない。使うには配列(コンテナ)を作って変数に入れてから使う。下の例を見てね。
- 事実6. 配列オブジェクト(コンテナ)を作る時は、長さ(セル数)を指定する。コマンドはnew TypeName[n];
- 事実7. 配列の長さは.Lengthプロパティで取得できる。
- 事実8. 配列を作った後は、要素の型も数も変えられない。
string s; // sはnull
string[] list; // listはnull
list = new string[10]; // list変数は10個の文字列配列オブジェクトの参照を持つ
int n = list.Length; // nは10
list = new string[0]; // listは0個の配列を持つ
// 配列はあるけど、要素は保存できない
list = null;
Console.WriteLine(list[1]); // プログラムエラーになる(強制終了)
// listはnull参照
list = new string[10];
Console.WriteLine(list[10]); // エラーになる(配列の範囲外アクセス)
// listが10個のセルを持ってる場合、使えるインデックスは0 1 2 3 4 5 6 7 8 9の10個だけ
GO TO FULL VERSION