配列変数
大量のデータを扱う場合の処理
前回までの内容で、C#言語のアルゴリズムの三大要素が全て出そろいました。しかし、これだけでは十分なプログラムができるわけではありません。冒頭にも書いた通りプログラムを記述するためにはアルゴリズムとデータ構造という二大要素があることは説明したと思います。
ここからは、いよいよデータ構造について説明していきます。実用的なプログラムを作るときに必要なデータ構造はたくさんありますが、ここでは特にここでは大量のデータを扱う場合に必要な配列(はいれつ)について説明します。
C#言語では、変数を用いて大量のデータを扱う場合、配列変数(はいれつへんすう)を用います。ここでは、配列変数の使い方を学ぶことにしましょう。
サンプルプログラム
配列変数について詳しく説明する前に、まずは以下のプログラムを入力・実行してみてください。
プロジェクト:Sample501/ファイル名Program.csusing System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Sample501 { class Program { static void Main(string[] args) { double one,two,three; double sum,avg; // 合計値、平均値を入れる変数 one = 1.2; two = 3.7; three = 4.1; // 変数の代入 Console.WriteLine(one + " " + two + " " + three); sum = one + two + three; // 合計値の計算 avg = sum / 3.0; // 平均値の計算 Console.WriteLine("合計値:" + sum); Console.WriteLine("平均値:" + avg); } } }
合計値:9
平均値:3
このケースは、数値が3つだからよいですが、もしももっと増えたらどうなるでしょう?four,five,と、次々に定義する変数の数を増やしていかなくてはなりません。 しかし、このプログラムを、以下のように変更すると、大変楽になります。
プロジェクト:Sample502/ファイル名Program.csusing System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Sample502 { class Program { static void Main(string[] args) { double[] d = new double[3]; d[0] = 1.2; d[1] = 3.7; d[2] = 4.1; // 変数の代入 double sum,avg; // 合計値、平均値を入れる変数 sum = 0.0; for(int i = 0; i < d.Length; i++){ Console.Write(d[i] + " "); sum += d[i]; } Console.WriteLine(); avg = sum / d.Length; Console.WriteLine("合計値:" + sum); Console.WriteLine("平均値:" + avg); } } }
実行結果は、Sample501と一緒です。若干プログラムは長くなってしまいましたが、もしも変数が5個、10個、100個・・・と増えたときを考えてみてください。こちらのほうが、プログラムを変更する手間が少なそうです。
配列の大きさ
13行目に出てくる、d.Lengthは、配列変数の成分の数を表します。この場合、dの成分は3つあるので、d.Lengthは3となります。
配列の長さこれを用いることにより、配列変数の長さを取得することができます。
配列変数
では、一体、このプログラムはどのような仕組みになっているのでしょうか?6行目に出てくる、double d[] = new double[3];という記述が、配列変数(はいれつへんすう)の宣言です。配列変数とは、同一の名前で多数のデータを格納できる変数のことで、単に配列(はいれつ)とも呼ばれます。配列の諸式は以下のようになります。
配列の宣言したがって、この例で13行目は、double[] d = new double[3];と書くこともできます。
配列変数にも、変数名が存在します。この場合、dが変数名になります。[]の中に記述されているのが、配列の大きさで、この場合、サイズは3になります。
添字
この処理により、d[0]、d[1]、d[2]という3つのdouble型の変数が使用可能になります(図5-1)。14行目から16行目の間で、これらの変数に値を代入しています。なお、ここで[]の中に書いてある数字を、添字(そえじ)と言います。例えば、「d[1] = 3.7;」という処理は、この配列の2番目の変数に、3.7という値を代入することを意味します(図5-2)。この数値は必ず0から始まりますので、配列の大きさが3の場合は、2までになります。
図5-1.配列の宣言 | 図5-2.配列変数への値の代入 |
---|
添字が、配列の範囲を超えていてもエラーにはなりませんが、実行時に異常終了したりすることがありますので、気をつけましょう。
配列変数を使うメリットは、実はこの添字が使えることにあります。19行目から22行目のforループの中で、添字に整数型変数iを用いています。これにより、プログラムを変更して、配列の大きさを変化させても、for文に条件式の値を変化させるだけで対応できます。
配列の初期化
ところで、配列変数の宣言と初期化ですが、もう少し、楽にならないものなのでしょうか?実は、以下のようにすると、配列変数の宣言と初期化を一度に行うことができます。
プロジェクト:Sample503/ファイル名Program.csusing System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Sample503 { class Program { static void Main(string[] args) { int[] n = { 5,4,3,2,1 }; string[] s = { "ABC","DEF","GHI" }; int i; // 整数型配列変数nの成分表示 for(i = 0; i < n.Length; i++){ Console.Write(n[i]+" "); } Console.WriteLine(); // 文字列型配列変数nの成分表示 for(i = 0; i < s.Length; i++){ Console.Write(s[i]+" "); } Console.WriteLine(); } } }
ABC DEF GHI
実行結果を見るとわかるように、13~14行目で行っている処理は、配列のを生成し、同時に値を代入しています。例えば、nについては、以下のような処理を行っています。
配列の宣言と初期化↓ この処理は、以下の処理に相当
int n[] = new int[5];
n[0] = 5;
n[1] = 4;
n[2] = 3;
n[3] = 2;
n[4] = 1;
文字列変数sについても同様で、3個の成分を作り、s[0]からs[2]に値を「ABC」「DEF」「GHI」にしています。
foreachループ
サンプルプログラム
4日目で、forやwhileを始めとする繰り返し処理について説明しました。それらと同様に、配列の内容の出力に使える繰り返し処理があります。それが、foreachです。これを使えば、forループよりもシンプルに配列の成分をすべて取得することができます。
プロジェクト:Sample504/ファイル名Program.csusing System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Sample504 { class Program { static void Main(string[] args) { int[] n = { 1, 2, 3, 4 }; foreach(int i in n){ Console.Write("{0} ",i); } Console.WriteLine(); } } }
foreachの書式
foreachの書式は、以下のようになります。
foreachの書式これにより、配列変数の値が、一つ一つ変数に入っていきます。そして、すべての値が変数に入ると、ループが終了します。配列の内容をすべて出力する場合は、forループを使うよりもこちらの方が便利です。
多次元配列
サンプルプログラム
次に、配列変数の応用である、多次元配列(たじげんはいれつ)について説明しましょう。多次元配列とは、複数の添字をつけることができる配列変数です。そのなかで、最も基本となる二次元配列の例をここでは紹介します。以下のプログラムを実行してみてください。
プロジェクト:Sample505/ファイル名Program.csusing System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Sample505 { class Program { static void Main(string[] args) { int[,] a = new int[3,4]; int m,n; // 二次元配列に値を代入 for(m = 0; m < 3; m++){ for(n = 0; n < 4; n++){ a[m,n] = m+n; } } // 二次元配列に値を出力 for (m = 0; m < 3; m++) { for (n = 0; n < 4; n++) { Console.Write("a[{0},{1}]={2} ", m, n, a[m, n]); } Console.WriteLine(); } } } }
a[1,0]=1 a[1,1]=2 a[1,2]=3 a[1,3]=4
a[2,0]=2 a[2,1]=3 a[2,2]=4 a[2,3]=5
二次元配列
二次元配列aには、2つの添え字をつけることができます。これにより、二次元の配列を作ることが可能です。(図5-3)
図5-3.二次元配列のイメージ |
---|
配列の最初の引数と、次の引数の間は、,(コンマ)で区切ります。同様にして、三次元、四次元といったた次元の配列を作ることも可能です。
多次元配列の宣言と成分へのアクセスの方法二次元配列 | int[,] a = new int[3,4]; | → | a[1,2] = 2; |
---|---|---|---|
三次元配列 | int[,,] a = new int[3,4,5] | → | a[1,2,3] = 2; |
四次元配列 | int[,,,] a = new int[3,4,5,6] | → | a[1,2,3,4] = 2; |
多次元配列の理由範囲は非常に高く、さまざまな表や、座標などのデータを表すものとして使用されます。わかりやすい例でいくと、表計算のような処理は、2次元配列を用いれば、非常に簡単に実現できます。
ジャグ配列
サンプルプログラム
Sample505では、長方形の形になる二次元配列でしたが、この配列の構造は、不揃いにすることができます。これを、ジャグ配列と言います。以下のサンプルを実行してみてください。
プロジェクト:Sample506/ファイル名Program.csusing System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Sample506 { class Program { static void Main(string[] args) { int[][] a = new int[][]{new int[]{0,1},new int[]{2},new int[]{3,4,5,6}}; // 成分の表示 for(int m = 0; m < a.Length; m++){ for(int n = 0; n < a[m].Length; n++){ Console.Write(a[m][n]+" "); } Console.WriteLine(); } } } }
2
3 4 5 6
このように、縦、横の成分がばらばらになるようなケースもあります。図にすると、以下のようなイメージになります。(図5-4.)
図5-4.不揃いな配列のイメージ |
---|
練習問題 : 問題5.