[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

コンピュータIIB(Javaプログラミング入門)第9回

目次
9.1 配列(1)
9.1.1 配列とは
9.1.2 配列の使い方
9.1.3 配列の初期化
9.1.4 配列と繰返し
9.1.5 配列の使用例
9.2 演習9
9.3 レポート課題
9.4 参考文献
索引
インデックス   初期化(配列の)   添字   配列   配列要素  

9.1 配列(1)

9.1.1 配列とは

変数を用いるとデータを一つ格納できることは、すでに学びました。 たくさんのデータを格納するには、データの個数だけ変数を用意すれば可能です。 しかし、それらのデータを系統的に取り扱うことは困難です。

配列array ) というものを用いると、たくさんのデータを系統的に格納することができます。 配列とは、データの「入れ物」が並んだものと考えてください。 次の図は、配列のイメージです。

配列のイメージ
図 9.1  配列のイメージ

「入れ物」の一つ一つを 配列要素array element ) とよびます。 配列には次のような特徴があります。

9.1.2 配列の使い方

変数を使うためには、変数の宣言が必要でした。 int x; のように変数を宣言すると、変数 x に整数( int 型)が一つ格納できました。

配列を使うためには、配列の宣言と配列の生成という二段階の手続きが必要です。 次のプログラムは、配列を宣言し、生成し、その3番目に整数23を格納し、それを出力するものです。

/*  1*/ class ArrayTest { // 配列のテスト
/*  2*/     public static void main (String[] args) {
/*  3*/         int[] a; // 宣言
/*  4*/         a = new int[10]; // 10個生成
/*  5*/         a[3] = 23; // 3番目に格納
/*  6*/         System.out.println(a[3]); // 3番目を出力
/*  7*/     }
/*  8*/ }
asiaa1:~/comp2b b08a001$ java ArrayTest
23
asiaa1:~/comp2b b08a001$

整数( int 型)の場合、配列の宣言は次のように書きます。

int[] 配列;

ここで、「 配列 」は配列の名前です。 配列の生成は、

配列 = new int[要素数];

と書きます。 ここで、「 要素数 」は配列の要素数です。

上記のプログラムでは、3行目で名前が a である配列を宣言しています。 また、4行目で要素数が10である配列を生成しています。

配列要素にデータを格納するには、

配列[番号] = ;

と書きます。 「 配列 」の「 番号 」番目の要素に「 」の値を格納します。 ここで、「 番号 」は数そのものである必要はありません。 数を値に持つならば、変数や式でもかまいません。 例えば、変数 i の値が3で x の値が100ならば、 b[i - 1] = x + 1; によって配列 b の2番目の要素に101が格納されます。 式

配列[番号]

で、「 配列 」の「 番号 」番目の要素が取り出せます。 なお、配列の何番目の要素かを表すこの「 番号 」を、配列の 添字subscript ) 、または インデックスindex ) とよびます。

上記のプログラムでは、5行目で配列の3番目の要素にデータ23を格納しています。 また、6行目ではそのデータを取り出して出力しています。

上記のプログラムにおいて、 a [10] は存在しないことに注意してください。 このような、存在しない要素にデータを格納しようとしたり、データを取り出そうとすると、エラーが発生します。

/*  1*/ class ArrayError { // 配列のエラー
/*  2*/     public static void main (String[] args) {
/*  3*/         int[] a;
/*  4*/         a = new int[10]; // 0番目から9番目まで
/*  5*/         a[10] = 100; // 10番目は存在しない
/*  6*/         System.out.println(100);
/*  7*/     }
/*  8*/ }
asiaa1:~/comp2b b08a001$ java ArrayError
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10
        at ArrayError.main(ArrayError.java:5)
asiaa1:~/comp2b b08a001$

なお、配列の要素数をどこかに記録しておく必要はありません。 これは、式

配列.length

によっていつでも取り出せます。

注意: 教科書によっては、配列の宣言は

int a[];

などと書くと説明しています。 Javaでは、 int[] a;int a[]; は同じ意味です。 ただし、これらを混在させるのは混乱のもとですので、この授業では前者に統一します。

9.1.3 配列の初期化

上記のイメージの通り、配列にデータを格納しましょう。 これは、配列の宣言、配列の生成、配列要素への代入という手順を踏むとできます。 以下はそのようなプログラム(部分)です。

int[] a;
a = new int[10];
a[0] = 20; a[1] = 21; a[2] = 22; a[3] = 23; a[4] = 24;
a[5] = 25; a[6] = 26; a[7] = 27; a[8] = 28; a[9] = 29;

次のように書くと、配列の宣言と生成が同時に行えます。

int[] a = new int[10]; // 宣言と生成
a[0] = 20; a[1] = 21; a[2] = 22; a[3] = 23; a[4] = 24;
a[5] = 25; a[6] = 26; a[7] = 27; a[8] = 28; a[9] = 29;

さらに、データの格納も同時に行うことができます。 これは次のように書きます。

int[] a = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29};

このことを、配列の 初期化initialization ) とよびます。 配列の初期化では、キーワード new や配列の要素数は書きません。

9.1.4 配列と繰返し

配列のプログラムでは、繰返しを利用するのが普通です。 つまり、ループ制御変数 i を用意し、 for 文などの繰返しの中で、配列要素 a [ i ]からデータを取り出したり、 a [ i ]にデータを格納したりします。

次のプログラムは、配列 a の要素をすべて出力するものです。

/*  1*/ class ArrayPrint { // 配列の出力
/*  2*/     public static void main (String[] args) {
/*  3*/         int i;
/*  4*/         int[] a = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29}; // 初期化
/*  5*/         for (i = 0; i < a.length; i++) { // aの要素数回繰り返す
/*  6*/             System.out.println("a[" + i + "] = " + a[i]);
/*  7*/         }
/*  8*/     }
/*  9*/ }
asiaa1:~/comp2b b08a001$ java ArrayPrint
a[0] = 20
a[1] = 21
a[2] = 22
a[3] = 23
a[4] = 24
a[5] = 25
a[6] = 26
a[7] = 27
a[8] = 28
a[9] = 29
asiaa1:~/comp2b b08a001$

4行目で配列 a を初期化します。 式 a . length の値は10なので、5行目の for 文では変数 i は0から9まで動きます。 6行目で配列要素 a [ i ]の値を詳しく出力します。

9.1.5 配列の使用例

配列の使用例として、はじめに絵グラフを出力します。 絵グラフとは、棒グラフの棒の代わりに、同じ絵が連続して描かれるグラフです。 ここでは、絵として星印(*)を用います。 グラフにするデータは以下の通りです。

表 9.1  絵グラフのデータ
添字 0 1 2 3 4 5 6 7
データ 8 6 6 8 9 7 6 6

プログラムは次の通りです。 配列からデータを取り出すループと、星印を出力するループの、2重ループになっています。

/*  1*/ class PictureGraph { // 絵グラフ
/*  2*/     public static void main (String[] args) {
/*  3*/         int i, j;
/*  4*/         int[] a = {8, 6, 6, 8, 9, 7, 6, 6};
/*  5*/         for (i = 0; i < a.length; i++) {
/*  6*/             System.out.print(i + ": ");
/*  7*/             for (j = 0; j < a[i]; j++) { // a[i]回繰り返す
/*  8*/                 System.out.print("*");
/*  9*/             }
/* 10*/             System.out.println();
/* 11*/         }
/* 12*/     }
/* 13*/ }
asiaa1:~/comp2b b08a001$ java PictureGraph
0: ********
1: ******
2: ******
3: ********
4: *********
5: *******
6: ******
7: ******
asiaa1:~/comp2b b08a001$

次の例は、配列要素の総和を求めるものです。

{100, 200, 100, 300, 200}

で表される配列の要素の合計を、レジの計算の要領で算出します。 つまり、

sum += a[0];
sum += a[1];
sum += a[2];
...

のように計算します。 プログラムは次の通りです。

/*  1*/ class ArraySummation { // 配列の総和
/*  2*/     public static void main (String[] args) {
/*  3*/         int i, sum = 0;
/*  4*/         int[] a = {100, 200, 100, 300, 200};
/*  5*/         for (i = 0; i < a.length; i++) {
/*  6*/             sum += a[i];
/*  7*/         }
/*  8*/         System.out.println("合計は" + sum);
/*  9*/     }
/* 10*/ }
asiaa1:~/comp2b b08a001$ java ArraySummation
合計は900
asiaa1:~/comp2b b08a001$

次の例は、配列要素の最大値を求めるものです。

{100, 200, 100, 300, 200}

で表される配列の要素の最大値は、人間が見れば 300 だと分かります。

この問題をコンピュータで解決するのに、勝ち抜き方式を使うことにします。 これは、はじめに最初の要素をとりあえずチャンピオンにします。 続いて、次の要素とチャンピオンが勝負をし、チャンピオンが負けたら勝者を新たにチャンピオンにします。 これを要素がなくなるまで繰り返します。 最後のチャンピオンが全体のチャンピオンであるというわけです。

具体的には、

max = a[0];
if (a[1] > max) {
    max = a[1];
}
if (a[2] > max) {
    max = a[2];
}
...

のようにして、最大値を求めます。 プログラムは次の通りです。

/*  1*/ class ArrayMaximum { // 配列の最大値
/*  2*/     public static void main (String[] args) {
/*  3*/         int i, max;
/*  4*/         int[] a = {100, 200, 100, 300, 200};
/*  5*/         max = a[0]; // とりあえずチャンピオンにする
/*  6*/         for (i = 1; i < a.length; i++) {
/*  7*/             if (a[i] > max) { // チャンピオンが負けたら
/*  8*/                 max = a[i]; // 勝者をチャンピオンにする
/*  9*/             }
/* 10*/         }
/* 11*/         System.out.println("最大値は" + max);
/* 12*/     }
/* 13*/ }
asiaa1:~/comp2b b08a001$ java ArrayMaximum
最大値は300
asiaa1:~/comp2b b08a001$

最後の例として、成績の集計を行います。 30人のクラスで試験をして、次のような得点データが得られたとします。

95, 80, 65, 0, 85, 100, 79, 85, 93, 0, 88, 90, 80, 98, 75, 95, 58, 85, 88, 70, 75, 82, 100, 60, 92, 55, 0, 95, 83, 81

これを10点刻みで分類し、得点分布を求めるプログラムを考えます。

はじめに、人数を数える配列 counts を用意します。 得点とこの配列の添え字を次のように対応させます。

表 9.2  得点と添字の対応
得点 添字
0〜9 0
10〜19 1
20〜29 2
30〜39 3
40〜49 4
50〜59 5
60〜69 6
70〜79 7
80〜89 8
90〜99 9
100 10

このように対応させると、得点 s から添字を求めるには、式 s /10 で計算できます。 また、添字 i から得点範囲を求めるには、式 i ×10 と i ×10+9 で計算できます。

次に、得点を格納する配列 scores を用意します。 配列の初期化を使って、これに得点を格納します。 このデータをひとつずつ取り出し、得点から添字を計算し、その分類の人数を1増加させるという操作を繰り返して、得点範囲ごとに人数を数えます。

10行目から12行目で、各分類の人数 counts [ i ] をすべて0にします。 13行目から15行目で、各得点 scores [ i ] から添字 scores [ i ] / 10 を求め、その分類の人数を1増やします。

最後に集計結果を出力します。 17行目で得点範囲を、18行目でその人数を、それぞれ改行せずに出力します。 改行は19行目で行います。

/*  1*/ class ScoreDistribution { // 得点の分布
/*  2*/     public static void main (String[] args) {
/*  3*/         int i;
/*  4*/         int[] counts = new int[11]; // 人数を格納する配列
/*  5*/         int[] scores = {
/*  6*/             95, 80, 65, 0, 85, 100, 79, 85, 93, 0,
/*  7*/             88, 90, 80, 98, 75, 95, 58, 85, 88, 70,
/*  8*/             75, 82, 100, 60, 92, 55, 0, 95, 83, 81
/*  9*/         };
/* 10*/         for (i = 0; i < counts.length; i++) {
/* 11*/             counts[i] = 0; // 最初は0人
/* 12*/         }
/* 13*/         for (i = 0; i < scores.length; i++) {
/* 14*/             counts[scores[i] / 10]++; // 人数を1増加
/* 15*/         }
/* 16*/         for (i = 0; i < counts.length; i++) {
/* 17*/             System.out.print((i * 10) + " - " + (i * 10 + 9) + " : ");
/* 18*/             System.out.print(counts[i]); // 人数を出力
/* 19*/             System.out.println();
/* 20*/         }
/* 21*/     }
/* 22*/ }
asiaa1:~/comp2b b08a001$ java ScoreDistribution
0 - 9 : 3
10 - 19 : 0
20 - 29 : 0
30 - 39 : 0
40 - 49 : 0
50 - 59 : 2
60 - 69 : 2
70 - 79 : 4
80 - 89 : 10
90 - 99 : 7
100 - 109 : 2
asiaa1:~/comp2b b08a001$

9.2 演習9

ある会社のある課には社員が30人います。 社員の年齢の分布を調べることになりました。 10代、20代、30代、40代、50代、60代の6種類に分類し、以下のように出力するプログラムを作成してください。 年齢のデータは次の通りです。

62, 48, 30, 55, 23, 47, 58, 33, 34, 57, 36, 19, 51, 41, 63, 28, 42, 32, 55, 64, 52, 60, 25, 63, 44, 30, 51, 37, 39, 44

このデータをプログラムの中に書き、配列の初期化の要領で配列に格納してください。 なお、10才未満や70才以上の人は、はじめからいないものとしてください。

asiaa1:~/comp2b b08a001$ java AgeDistribution
10代: 1
20代: 3
30代: 8
40代: 6
50代: 7
60代: 5
asiaa1:~/comp2b b08a001$

余力のある人は、絵グラフを出力してください。

asiaa1:~/comp2b b08a001$ java AgeDistribution2
10代: *
20代: ***
30代: ********
40代: ******
50代: *******
60代: *****
asiaa1:~/comp2b b08a001$

9.3 レポート課題

今日の演習9の答案(Javaプログラム)をメールで提出してください。 差出人は学内のメール・アドレス(b08a001@cis.twcu.ac.jpなど)とし、宛先はkonishi@cis.twcu.ac.jpとします。 メールの本文には、学生番号、氏名、科目名、授業日(6月24日)を明記してください。


9.4 参考文献


[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

2011年6月24日更新
小西 善二郎 <konishi@cis.twcu.ac.jp>
Copyright (C) 2011 Zenjiro Konishi. All rights reserved.