++C++; // 未確認飛行 C

Google
Web ufcpp.net

配列

目次

キーワード

概要

「複数の数値を入力してその和を求める」とかいうように、複数のデータを一まとめにして扱いたい場合があります。 C# などのプログラミング言語には、 複数のデータを一まとめにするための「配列」というものがあります。

配列がなかったら

まずは、もし複数のデータを一まとめにせずにばらばらに扱おうとするとどうなるか考えてみましょう。 例として、5個の整数を入力して、それらの二乗和を求めることを考えます。 プログラムは以下のようになるでしょう。

int a, b, c, d, e; // 変数を入力したいデータの数だけ用意。

// 値の入力
a = int.Parse(Console.ReadLine());
b = int.Parse(Console.ReadLine());
c = int.Parse(Console.ReadLine());
d = int.Parse(Console.ReadLine());
e = int.Parse(Console.ReadLine());

// 値の計算
int square_sum = a*a + b*b + c*c + d*d + e*e;

// 値の出力
Console.Write("二乗和は {0} です", square_sum);

似たような文が何度も繰り返し出てきています。 これは書くのにも手間がかかりますし、修正が必要になった場合、何箇所も修正する必要が出てきます。 それに、入力するデータの数を5個から10個とかいうように変更したい場合にも、修正が大変になります。

配列を使う

C# には複数のデータを一まとめにするために配列というものが用意されています。 先ほどの例では、5個のデータをa, b, c, d, eという5つの変数に格納していましたが、 配列を使うことでa[0], a[1], a[2], a[3], a[4]というように、番号を振って管理出来ます。

配列は以下のようにして宣言します。 すなわち、 型名に [] を付けることで配列型を作ることができます

型名[] 変数名;

配列は宣言しただけでは利用できず、まずは配列の実体を作成する必要があります。 実体の作成は new というキーワードを用いて以下のようにします。

配列型変数 = new 型名[配列の長さ];

詳しくは 「クラス」 で説明しますが、 配列型の変数というのは配列を格納するためのただの入れ物で、 配列の実体を作成して変数に格納してやる必要があります。 new はこの実体を作成するための演算子です。

先ほどの例を配列を使って書き直してみましょう。

int[] a = new int[5]; // 長さが5の整数型配列を用意。

// 値の入力
for(int i=0; i<a.Length; ++i) // a.Length は配列 a の長さ。これの例では5。
{
  a[i] = int.Parse(Console.ReadLine());
}

// 値の計算
int square_sum;
for(int i=0; i<a.Length; ++i)
{
  square_sum += a[i]*a[i];
}

// 値の出力
Console.Write("二乗和は {0} です", square_sum);

配列を使うことで、手動で何度も繰り返し書いていた文が1つの for 文にまとまりました。 書く手間は1度ですみますし、修正も1箇所で済みます。 また、入力したいデータの数を変更したい場合にも、最初の1行を修正するだけで済みます。

サンプル

using System;

class ArraySample
{
  public static void Main()
  {
    // フィボナッチ数列の20項目までを求める
    int[] sequence = new int[20];

    // 最初の2項を入力
    Console.Write("a1 = ");
    sequence[0] = int.Parse(Console.ReadLine());
    Console.Write("a2 = ");
    sequence[1] = int.Parse(Console.ReadLine());

    // 漸化式を使って20項目までを計算
    for(int i=2; i<sequence.Length; ++i)
    {
      sequence[i] = sequence[i-1] + sequence[i-2];
    }

    // 結果の出力
    Console.Write("{");
    for(int i=0; i<sequence.Length-1; ++i)
    {
      Console.Write(sequence[i] + ", ");
    }
    Console.Write(sequence[sequence.Length-1] + "}");
  }
}
a1 = 2
a2 = 1
{2, 1, 3, 4, 7, 11, 18, 29, 47, 76, 123, 199, 322, 521, 843, 1364, 2207,
 3571, 5778, 9349}

また、配列は以下のようにして宣言時に初期化することも出来ます。

型名[] 変数名 = new 型名[] {値1, 値2, .....};

例えば、1, 3, 5, 7, 9 という初期値を持った int 型配列を作成するには以下のようにします。

int[] a = new int[] {1, 3, 5, 7, 9};

暗黙的型付け配列

Ver. 3.0

C# 3.0 では、 配列の初期化時の、「new 型名[]」の型名を省略することが可能に成りました。

int[] a = new[] {1, 3, 5, 7, 9};

配列の型は、{} の中身から推論されます。

多次元配列

今までは1次元的に並んだデータを格納するための1次元配列について説明してきました。 しかし、画像などのように、データが多次元的に並んでいる場合もあります。 C# ではそのような多次元データを格納するため、多次元配列が用意されています。 多次元配列は以下のようにして宣言します。

型名[,] 変数名; // 2次元配列
型名[,,] 変数名; // 3次元配列

1次元配列のときと同じく、new キーワードを用いて配列を作成する必要があります。

変数名 = new 型名[長さ1, 長さ2]; // 2次元配列の場合
変数名 = new 型名[長さ1, 長さ2, 長さ3]; // 3次元配列の場合

また、宣言時に値を初期化する場合には以下のようにします。

型名[,] 変数名 = new 型名[,] {
  {値1-1, 値1-2, .....},
  {値2-1, 値2-2, .....},
  .....
};

例えば、2次元配列を行列に見立てて行列の掛け算を行うプログラムは以下のようになります。

double[,] a = new double[,]{{1, 2}, {2, 1}, {0, 1}}; // 3行2列の行列
double[,] b = new double[,]{{1, 2, 0}, {0, 1, 2}};   // 2行3列の行列
double[,] c = new double[3, 3];                      // 3行3列の行列

for(int i=0; i<a.GetLength(0); ++i) // a.GetLength(0) は a の行数を表す。
{
  for(int j=0; j<b.GetLength(1); ++j) // b.GetLength(1) は b の列数を表す。
  {
    c[i, j] = 0;
    for(int k=0; k<a.GetLength(1); ++k) // a.GetLength(1) は a の列数を表す。
    {
      c[i, j] += a[i, k] * b[k, j];
    }
  }
}

配列の配列

多次元のデータを扱うためには array[x, y] という構文で使用する多次元配列の他に、 「配列の配列」を使う方法もあります。 「配列の配列」とはその名の通り、配列(型名[])をさらに配列にしたもの(型名[][])です。

例として、多次元配列のところで挙げた行列の掛け算を配列の配列を使って書き直すと以下のようになります。

double[][] a = new double[][]{  // 3行2列の行列
  new double[]{1, 2},
  new double[]{2, 1},
  new double[]{0, 1}
};
double[][] b = new double[][]{  // 2行3列の行列
  new double[]{1, 2, 0},
  new double[]{0, 1, 2}
};
double[][] c = new double[3][]; // 3行3列の行列
for(int i=0; i<c.Length; ++i)
  c[i] = new double[3];

for(int i=0; i<a.Length; ++i) // a.Length は a の行数を表す。
{
  for(int j=0; j<b[0].Length; ++j) // b[0].Length は b の列数を表す。
  {
    c[i, j] = 0;
    for(int k=0; k<a[0].Length; ++k) // a[0].Length は a の列数を表す。
    {
      c[i, j] += a[i, k] * b[k, j];
    }
  }
}

「多次元配列」は全ての行の列数が同じになりますが、 「配列の配列」は各列毎に列数が異なっていても構いません。 そのため、「多次元配列」のことを“Rectangular Array”(四角い配列)、 「配列の配列」のことを“Jagged Array” (ぎざぎざ配列)という言うこともあります。

「配列の配列」は「多次元配列」と比べ、 動作が少しだけ高速であるという事と、列数を自由に変えられるという利点がありますが、 メモリ利用効率が少々悪いという事と、宣言・初期化が面倒であるという欠点があります。

演習問題

問題 1

for 文を使って以下の漸化式の一般項 an を20項目まで求めるプログラムを作成せよ。 ( an を配列で表す。)

an + 2 = 2 an + 1 - 2 an
a0 = 3
a1 = 1

解答

問題 2

int 型の配列に格納されている値の最大値、最小値および平均値を求めよ。 できれば、配列の長さ n および n 個の整数値をユーザに入力してもらうようにすること。

解答

問題 3

double 型の2次元配列を行列に見立てて、行列の掛け算を行うプログラムを作成せよ。

解答

Transtation into English

[お問い合わせ](q)