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

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

目次
7.1 データの入出力(3)
7.1.1 エスケープ・シーケンス
7.2 配列(2)
7.2.1 配列要素の挿入と削除
7.2.2 配列のコピー
7.2.3 配列への入力
7.2.4 並列配列
7.3 演習7
7.4 レポート課題
7.5 参考文献
索引
エスケープ・シーケンス   並列配列  

7.1 データの入出力(3)

7.1.1 エスケープ・シーケンス

「ターミナル」に"Good afternoon!"と出力するには、

System.out.println("Good afternoon!");

と書きました。 では、ダブルクオートも出力するにはどうすればよいでしょうか。 正解は、

System.out.println("\"Good afternoon!\"");

です。

文字列"\""がダブルクオートの代りになるように、直接扱いにくい文字の代りとなる文字列を、 エスケープ・シーケンスescape sequence ) とよびます。 Javaのエスケープ・シーケンスは以下の通りです。 ここで、タブとは一定のきざみ(たいていは8文字単位)の位置まで設けられる間隔のことです。 データを表のような形式で出力するときに役に立ちます。

表 7.1  エスケープ・シーケンス
\b バックスペース
\t タブ
\n 改行
\f フォームフィード
\r 復帰
\" ダブルクオート
\' シングルクオート
\\ バックスラッシュ

注意: 記号"\"は、場合によってバックスラッシュになったり円記号になったりします。 エスケープ・シーケンスが使えないときは、バックスラッシュと円記号を入れ替えてみてください。


7.2 配列(2)

7.2.1 配列要素の挿入と削除

前回、配列は、一度用意すると要素数は変えられないと言いました。 要素数を5個に決めたら、ずっと5個のままです。 しかし、配列に要素を挿入したり、配列から要素を削除したい場合もあるでしょう。 この問題を解決するには、次のような方法が考えられます。

ここでは、大きな配列を用意する方法について説明します。 配列をコピーする方法については、次の小節で説明します。

大きな配列の最初の部分を使うには、配列の要素数とは別に、データの個数を覚えておきます。 例えば、データの個数を変数 count で表します。 そして、 for 文などで、配列の要素数 a .lengthの代わりに、 count を使います。

次のプログラムでは、配列の要素数は10, データの個数は5として、すべてのデータを出力しています。

/*  1*/ class ArrayStack {
/*  2*/     public static void main (String[] args) {
/*  3*/         int[] a = {10, 11, 12, 13, 14, 0, 0, 0, 0, 0}; // 要素数は10
/*  4*/         int i, count = 5; // データの個数は5
/*  5*/         for (i = 0; i < count; i++) { // データの個数回繰り返す
/*  6*/             System.out.println("a[" + i + "] = " + a[i]);
/*  7*/         }
/*  8*/     }
/*  9*/ }
asiaa1:~/comp2b b08a001$ java ArrayStack
a[0] = 10
a[1] = 11
a[2] = 12
a[3] = 13
a[4] = 14
asiaa1:~/comp2b b08a001$

この配列にデータ15を挿入するには、 a [ count ]を15にし、 count を1増加させます。

/*  1*/ class ArrayPush {
/*  2*/     public static void main (String[] args) {
/*  3*/         int[] a = {10, 11, 12, 13, 14, 0, 0, 0, 0, 0};
/*  4*/         int i, count = 5;
/*  5*/         a[count] = 15; // データを挿入
/*  6*/         count++; // データの個数を1増加
/*  7*/         for (i = 0; i < count; i++) {
/*  8*/             System.out.println("a[" + i + "] = " + a[i]);
/*  9*/         }
/* 10*/     }
/* 11*/ }
asiaa1:~/comp2b b08a001$ java ArrayPush
a[0] = 10
a[1] = 11
a[2] = 12
a[3] = 13
a[4] = 14
a[5] = 15
asiaa1:~/comp2b b08a001$

元の配列から最後のデータ14を削除するには、 count を1減少させます。 プログラムでは、 a [ count ]を0にしていますが、本当は必要ありません。

/*  1*/ class ArrayPop {
/*  2*/     public static void main (String[] args) {
/*  3*/         int[] a = {10, 11, 12, 13, 14, 0, 0, 0, 0, 0};
/*  4*/         int i, count = 5;
/*  5*/         count--; // データの個数を1減少
/*  6*/         a[count] = 0; // やらなくてもよい
/*  7*/         for (i = 0; i < count; i++) {
/*  8*/             System.out.println("a[" + i + "] = " + a[i]);
/*  9*/         }
/* 10*/     }
/* 11*/ }
asiaa1:~/comp2b b08a001$ java ArrayPop
a[0] = 10
a[1] = 11
a[2] = 12
a[3] = 13
asiaa1:~/comp2b b08a001$

7.2.2 配列のコピー

整数( int 型)の変数 x から変数 y にコピーするには、代入文 y = x; でできます。 しかし、配列の変数 a の要素から変数 b の要素にコピーするには、 b = a; ではできません。

b[0] = a[0];
b[1] = a[1];
b[2] = a[2];
...

のように、一つ一つ配列要素をコピーする必要があります。

配列のコピー
図 7.1  配列のコピー

次のプログラムは、配列 a の要素から配列 b の要素にコピーし、 b の要素を出力するものです。

/*  1*/ class ArrayCopy {
/*  2*/     public static void main (String[] args) {
/*  3*/         int i;
/*  4*/         int[] a = {10, 11, 12, 13, 14};
/*  5*/         int[] b = new int[a.length]; // 同じ要素数の配列を生成
/*  6*/         for (i = 0; i < a.length; i++) {
/*  7*/             b[i] = a[i]; // 要素ごとにコピー
/*  8*/         }
/*  9*/         for (i = 0; i < b.length; i++) {
/* 10*/             System.out.println("b[" + i + "] = " + b[i]);
/* 11*/         }
/* 12*/     }
/* 13*/ }
asiaa1:~/comp2b b08a001$ java ArrayCopy
b[0] = 10
b[1] = 11
b[2] = 12
b[3] = 13
b[4] = 14
asiaa1:~/comp2b b08a001$

5行目で、配列 a と同じ要素数の配列 b を宣言し、生成します。 6行目から8行目でコピーが行われます。 式 a .lengthの値は5なので、6行目の for 文では変数 i は0から4まで動きます。 これは、配列 ab の添字の範囲と一致します。

配列をコピーする方法で、この配列にデータ15を挿入するには、まず、要素数が1個多い配列を新たに生成します。 そして、元の配列から新しい配列にコピーして、新しい配列にデータ15を挿入します。

/*  1*/ class ArrayInsert {
/*  2*/     public static void main (String[] args) {
/*  3*/         int i;
/*  4*/         int[] a = {10, 11, 12, 13, 14};
/*  5*/         int[] b = new int[a.length + 1]; // 1個多く生成
/*  6*/         for (i = 0; i < a.length; i++) { // すべてコピー
/*  7*/             b[i] = a[i];
/*  8*/         }
/*  9*/         b[a.length] = 15; // データを挿入
/* 10*/         for (i = 0; i < b.length; i++) {
/* 11*/             System.out.println("b[" + i + "] = " + b[i]);
/* 12*/         }
/* 13*/     }
/* 14*/ }
asiaa1:~/comp2b b08a001$ java ArrayInsert
b[0] = 10
b[1] = 11
b[2] = 12
b[3] = 13
b[4] = 14
b[5] = 15
asiaa1:~/comp2b b08a001$

配列をコピーする方法で、元の配列から最後のデータ14を削除するには、まず、要素数が1個少ない配列を新たに生成します。 そして、元の配列から新しい配列にコピーします。 ただし、元の配列の最後の要素はコピーしません。

/*  1*/ class ArrayDelete {
/*  2*/     public static void main (String[] args) {
/*  3*/         int i;
/*  4*/         int[] a = {10, 11, 12, 13, 14};
/*  5*/         int[] b = new int[a.length - 1]; // 1個少なく生成
/*  6*/         for (i = 0; i < a.length - 1; i++) { // 最後以外をコピー
/*  7*/             b[i] = a[i];
/*  8*/         }
/*  9*/         for (i = 0; i < b.length; i++) {
/* 10*/             System.out.println("b[" + i + "] = " + b[i]);
/* 11*/         }
/* 12*/     }
/* 13*/ }
asiaa1:~/comp2b b08a001$ java ArrayDelete
b[0] = 10
b[1] = 11
b[2] = 12
b[3] = 13
asiaa1:~/comp2b b08a001$

7.2.3 配列への入力

ここでは、配列の初期化ではなく、プログラムの実行時に、配列にデータを入力する方法を考えてみます。 この場合、データの個数があらかじめ分かっているかどうかで、配列の使い方が変わります。 あらかじめ分かっていない場合は、まず、大きめの配列を用意します。 そして、 count などの変数でデータの個数を数えながら、入力されたデータを配列に挿入していきます。 データの終わりを判定するために、何か特別な値(-1など)が入力されたら入力終了と見なします。

/*  1*/ import java.io.*;
/*  2*/
/*  3*/ class ArrayInput {
/*  4*/     public static void main (String[] args) throws IOException {
/*  5*/         InputStreamReader isr = new InputStreamReader(System.in);
/*  6*/         BufferedReader br = new BufferedReader(isr);
/*  7*/         int[] a = new int[10]; // データは10個まで
/*  8*/         int i, input, count = 0; // 最初は0個
/*  9*/         System.out.println("データは" + a.length + "個までです。");
/* 10*/         System.out.println("終了は-1を入力してください。");
/* 11*/         System.out.print("a[" + count + "] = ? ");
/* 12*/         input = Integer.parseInt(br.readLine()); // 入力
/* 13*/         while (input != -1) { // 入力が終了するまで繰り返す
/* 14*/             a[count] = input; // 挿入
/* 15*/             count++; // 1増加
/* 16*/             System.out.print("a[" + count + "] = ? ");
/* 17*/             input = Integer.parseInt(br.readLine()); // 入力
/* 18*/         }
/* 19*/         for (i = 0; i < count; i++) {
/* 20*/             System.out.println("a[" + i + "] = " + a[i]);
/* 21*/         }
/* 22*/     }
/* 23*/ }
asiaa1:~/comp2b b08a001$ java ArrayInput
データは10個までです。
終了は-1を入力してください。
a[0] = ? 10
a[1] = ? 11
a[2] = ? 12
a[3] = ? 13
a[4] = ? 14
a[5] = ? -1
a[0] = 10
a[1] = 11
a[2] = 12
a[3] = 13
a[4] = 14
asiaa1:~/comp2b b08a001$

あらかじめデータの個数が分かっている場合は、まず、データの個数を入力させます。 そして、その要素数の配列を生成し、配列要素を一つずつ入力させます。 この場合は、終了を表す特別な値を使わなくてもよいです。

/*  1*/ import java.io.*;
/*  2*/
/*  3*/ class ArrayInput2 {
/*  4*/     public static void main (String[] args) throws IOException {
/*  5*/         InputStreamReader isr = new InputStreamReader(System.in);
/*  6*/         BufferedReader br = new BufferedReader(isr);
/*  7*/         int i, input;
/*  8*/         System.out.print("データの個数を入力してください: ");
/*  9*/         input = Integer.parseInt(br.readLine()); // 入力
/* 10*/         int[] a = new int[input]; // 個数が分かってから配列を生成
/* 11*/         for (i = 0; i < a.length; i++) {
/* 12*/             System.out.print("a[" + i + "] = ? ");
/* 13*/             input = Integer.parseInt(br.readLine()); // 入力
/* 14*/             a[i] = input; // 挿入
/* 15*/         }
/* 16*/         for (i = 0; i < a.length; i++) {
/* 17*/             System.out.println("a[" + i + "] = " + a[i]);
/* 18*/         }
/* 19*/     }
/* 20*/ }
asiaa1:~/comp2b b08a001$ java ArrayInput2
データの個数を入力してください: 5
a[0] = ? 10
a[1] = ? 11
a[2] = ? 12
a[3] = ? 13
a[4] = ? 14
a[0] = 10
a[1] = 11
a[2] = 12
a[3] = 13
a[4] = 14
asiaa1:~/comp2b b08a001$

7.2.4 並列配列

次のような表の形のデータは、データをまとめるときによく使われます。

表 7.2  表の形のデータ
No. 0 1 2 3 4
項目A 10 11 12 13 14
項目B 20 21 22 23 24
項目C 30 31 32 33 34

このような表の形のデータは、配列をいくつか用意し、添字を使って配列要素を結び付けるとうまく処理できます。 このように使われる配列を 並列配列parallel array )とよびます。

この場合なら、項目Aを配列 a に格納し、項目Bを配列 b に格納し、項目Cを配列 c に格納します。 すると、0番目のデータは、項目Aが a [0], 項目Bが b [0], 項目Cが c [0] となります。 1番目のデータは、項目Aが a [1], 項目Bが b [1], 項目Cが c [1] などとなるわけです。

プログラムでは、タブ"\t"を使って、表に近い形でこのデータを出力しています。

/*  1*/ class ParallelArrays {
/*  2*/     public static void main (String[] args) {
/*  3*/         int i;
/*  4*/         int[] a = {10, 11, 12, 13, 14}; // 項目A
/*  5*/         int[] b = {20, 21, 22, 23, 24}; // 項目B
/*  6*/         int[] c = {30, 31, 32, 33, 34}; // 項目C
/*  7*/         System.out.println("No.\t項目A\t項目B\t項目C");
/*  8*/         for (i = 0; i < a.length; i++) {
/*  9*/             System.out.print(i + "\t");
/* 10*/             System.out.print(a[i] + "\t");
/* 11*/             System.out.print(b[i] + "\t");
/* 12*/             System.out.println(c[i]); // 行末で改行
/* 13*/         }
/* 14*/     }
/* 15*/ }
asiaa1:~/comp2b b08a001$ java ParallelArrays
No.     項目A   項目B   項目C
0       10      20      30
1       11      21      31
2       12      22      32
3       13      23      33
4       14      24      34
asiaa1:~/comp2b b08a001$

並列配列の例として、以下の長方形の総面積を計算します。

表 7.3  長方形の大きさ
No. 0 1 2 3 4
20 50 40 10 60
高さ 30 10 20 70 10

まず、配列 widthheight を初期化して、 i 番目の長方形の幅が width [ i ], 高さが height [ i ] になるようにします。 i 番目の長方形の面積 area は、 width [ i ] * height [ i ] で求められます。 総面積を計算するには、この area の値を areaSum に足していきます。

プログラムは次の通りです。

/*  1*/ class RectangleArea {
/*  2*/     public static void main (String[] args) {
/*  3*/         int i, area, areaSum = 0;
/*  4*/         int[] width = {20, 50, 40, 10, 60}; // 幅
/*  5*/         int[] height = {30, 10, 20, 70, 10}; // 高さ
/*  6*/         System.out.println("No.\t幅\t高さ\t面積");
/*  7*/         for (i = 0; i < width.length; i++) {
/*  8*/             area = width[i] * height[i]; // 面積の計算
/*  9*/             areaSum = areaSum + area; // 合計の計算
/* 10*/             System.out.print(i + "\t");
/* 11*/             System.out.print(width[i] + "\t");
/* 12*/             System.out.print(height[i] + "\t");
/* 13*/             System.out.println(area);
/* 14*/         }
/* 15*/         System.out.println("合計\t\t\t" + areaSum);
/* 16*/     }
/* 17*/ }
asiaa1:~/comp2b b08a001$ java RectangleArea
No.     幅      高さ    面積
0       20      30      600
1       50      10      500
2       40      20      800
3       10      70      700
4       60      10      600
合計                    3200
asiaa1:~/comp2b b08a001$

7.3 演習7

ある会社では、社員構成が次の通りであるとします。

表 7.4  ある会社の社員構成
年齢 10代 20代 30代 40代 50代 60代
男性 0 4 9 8 7 1
女性 3 5 6 2 0 0

このデータを配列 malefemale に格納して、年齢ごとの社員数と全社員数を計算します。 この計算のアルゴリズムを考え、プログラムを作成してください。 年齢の表示は、 i 番目を ( i + 1) * 10 + "代" とすればうまくいきます。

asiaa1:~/comp2b b08a001$ java CompanyStaffs
年齢    男性    女性    合計
10代    0       3       3
20代    4       5       9
30代    9       6       15
40代    8       2       10
50代    7       0       7
60代    1       0       1
合計                    45
asiaa1:~/comp2b b08a001$

余力のある人は、全体の男性社員数と女性社員数も計算してください。

asiaa1:~/comp2b b08a001$ java CompanyStaffs
年齢    男性    女性    合計
10代    0       3       3
20代    4       5       9
30代    9       6       15
40代    8       2       10
50代    7       0       7
60代    1       0       1
合計    29      16      45
asiaa1:~/comp2b b08a001$

7.4 レポート課題

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


7.5 参考文献


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

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