データの出力で使う
System.out.println(
data
);
や
System.out.print(
data
);
の
data
の所では、文字列や変数などを演算子
+
で結ぶことができます。
/* 1*/ class IntToString { /* 2*/ public static void main (String[] args) { /* 3*/ int x = 100; /* 4*/ System.out.println("x"); /* 5*/ System.out.println(x); /* 6*/ System.out.println("x is " + x); /* 7*/ } /* 8*/ }
b04a001@AsiaA1:~/comp2b% java IntToString x 100 x is 100 b04a001@AsiaA1:~/comp2b%
実は、この演算子
+
は文字列の連結です。
一方だけが文字列のときは、他方を文字列に変換して連結するという約束になっています。
整数と整数の足し算も
+
ですので、混乱しそうでしたら括弧を使ってください。
「ターミナル」に"Good afternoon!"と出力するには、
System.out.println("Good afternoon!");
と書きました。 では、ダブルクオートも出力するにはどうすればよいでしょうか。 正解は、
System.out.println("\"Good afternoon!\"");
です。
文字列"\""がダブルクオートの代りになるように、直接扱いにくい文字の代りとなる文字列を、 エスケープ・シーケンス ( escape sequence ) とよびます。 Javaのエスケープ・シーケンスは以下の通りです。 ここで、タブとは一定のきざみ(たいていは8文字単位)の位置まで設けられる間隔のことです。 データを表のような形式で出力するときに役に立ちます。
\n | 改行 |
\t | タブ |
\b | バックスペース |
\r | 復帰 |
\f | フォームフィード |
\\ | バックスラッシュ |
\' | シングルクオート |
\" | ダブルクオート |
注意: 記号"\"は、場合によって円記号になったりバックスラッシュになったりします。 混乱を避けるため、プログラムでは円記号を入力し、ファイルの文字コードをシフトJISにして保存してください。 コピー・アンド・ペーストした場合は、バックスラッシュを円記号に置き換えてください。
注意: Jeditは文字コードを自動判定しますが、手掛かりが少ないと判定に失敗します。 この対策として、コメントに文字コードの差異が明らかな文字列を入れます。 1行目を"// 文字コード判定用コメント"などとしてシフトJISで保存しますと、文字コードの判定ミスがなくなります。
変数を用いますと、データを一つ格納できることはすでに学びました。 たくさんのデータを格納するには、データの個数だけ変数を用意すれば可能です。 しかし、これらのデータを系統的に取り扱うことは困難です。
配列 ( array ) というものを用いますと、たくさんのデータを系統的に格納することができます。 配列とは、データの「入れ物」が並んだものと考えてください。 次の図は、配列のイメージです。
「入れ物」の一つ一つを 配列要素 ( array element ) とよびます。 配列には次のような特徴があります。
int
型)の隣に文字列(
String
型)を格納したりはできません。
変数を使うためには、変数の宣言が必要でした。
int x;
のように変数を宣言しますと、変数
x
に整数(
int
型)が一つ格納できました。
配列を使うためには、配列の宣言と配列の生成という二段階の手続きが必要です。 次のプログラムは、配列を宣言し、生成し、その3番目に整数72を格納し、それを出力するものです。
/* 1*/ class ArrayTest { /* 2*/ public static void main (String[] args) { /* 3*/ int[] a; /* 4*/ a = new int[10]; /* 5*/ a[3] = 72; /* 6*/ System.out.println(a[3]); /* 7*/ } /* 8*/ }
b04a001@AsiaA1:~/comp2b% java ArrayTest 72 b04a001@AsiaA1:~/comp2b%
整数(
int
型)の場合、配列の宣言は次のように書きます。
int[] arrayname;
ここで、 arrayname は配列の変数名です。 配列の生成は、
arrayname = new int[size];
と書きます。 ここで、 size は配列の要素数です。
上記のプログラムでは、3行目で変数名が a である配列を宣言しています。 また、4行目で要素数が10である配列を生成しています。
配列要素にデータを格納するには、
arrayname[index] = expression;
と書きます。
index
番目の要素に式
expression
の値を格納します。
ここで、
index
は数そのものである必要はありません。
数を値に持つならば、変数や式でもかまいません。
例えば、変数
i
の値が3で
x
の値が100ならば、
b[i - 1] = x + 1;
によって配列
b
の2番目の要素に101が格納されます。
式
arrayname[index]
は、配列の index 番目の要素に格納されたデータを値とします。 なお、配列の何番目の要素かを表すこの式 index を、配列の 添字 ( subscript ) 、または インデックス ( index ) とよびます。
上記のプログラムでは、5行目で配列の3番目の要素にデータ72を格納しています。 また、6行目ではそのデータを取り出して出力しています。
上記のプログラムでにおいて、 a [10] は存在しないことに注意してください。 このような、存在しない要素にデータを格納しようとしたり、データを取り出そうとしますと、エラーが発生します。
/* 1*/ class ArrayError { /* 2*/ public static void main (String[] args) { /* 3*/ int[] a; /* 4*/ a = new int[10]; /* 5*/ a[10] = 100; /* 6*/ System.out.println(100); /* 7*/ } /* 8*/ }
b04a001@AsiaA1:~/comp2b% java ArrayError Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10 at ArrayError.main(ArrayError.java:5) b04a001@AsiaA1:~/comp2b%
なお、配列の要素数をどこかに記録しておく必要はありません。 これは、式
arrayname.length
によっていつでも取り出せます。
注意: 教科書によっては、配列の宣言は
int a[];
などと書くと説明しています。
Javaでは、
int[] a;
と
int a[];
は同じ意味です。
ただし、これらを混在させるのは混乱のもとですので、この授業では前者に統一します。
上記のイメージの通り、配列にデータを格納しましょう。 これは、配列の宣言、配列の生成、配列要素への代入という手順を踏むとできます。 以下はそのようなプログラム(部分)です。
int[] a; a = new int[10]; a[0] = 99; a[1] = 90; a[2] = 81; a[3] = 72; a[4] = 63; a[5] = 54; a[6] = 45; a[7] = 36; a[8] = 27; a[9] = 18;
次のように書きますと、配列の宣言と生成が同時に行えます。
int[] a = new int[10]; a[0] = 99; a[1] = 90; a[2] = 81; a[3] = 72; a[4] = 63; a[5] = 54; a[6] = 45; a[7] = 36; a[8] = 27; a[9] = 18;
さらに、データの格納も同時に行うことができます。 これは次のように書きます。
int[] a = {99, 90, 81, 72, 63, 54, 45, 36, 27, 18};
このことを、配列の
初期化
(
initialization
)
とよびます。
配列の初期化では、キーワード
new
や配列の大きさは書きません。
整数(
int
型)の変数
x
から変数
y
にコピーするには、代入文
y = x;
でできます。
しかし、配列の変数
a
の要素から変数
b
の要素にコピーするには、
b = a;
ではできません。
b[0] = a[0]; b[1] = a[1]; b[2] = a[2]; ...
のように、一つ一つ配列要素をコピーする必要があります。
次のプログラムは、配列 a の要素から配列 b の要素にコピーし、 b の要素を出力するものです。
/* 1*/ class ArrayCopy { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ int[] a = {99, 90, 81, 72, 63, 54, 45, 36, 27, 18}; /* 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 + "] is " + b[i]); /* 11*/ } /* 12*/ } /* 13*/ }
b04a001@AsiaA1:~/comp2b% java ArrayCopy b[0] is 99 b[1] is 90 b[2] is 81 b[3] is 72 b[4] is 63 b[5] is 54 b[6] is 45 b[7] is 36 b[8] is 27 b[9] is 18 b04a001@AsiaA1:~/comp2b%
5行目で、配列
a
と同じ要素数の配列
b
を宣言し、生成します。
6行目から8行目でコピーが行われます。
式
a
.
length
の値は10ですので、6行目の
for
文では変数
i
は0から9まで動きます。
これは、配列
a
(および配列
b
)の添字の範囲と一致します。
9行目から11行目で配列
b
の要素を詳しく出力します。
配列の使用例として、はじめに配列要素の総和を求めます。
{100, 200, 100, 300, 200}
で表される配列の要素の合計を、レジの計算の要領で算出します。 つまり、
sum = sum + a[0]; sum = sum + a[1]; sum = 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 = sum + a[i]; /* 7*/ } /* 8*/ System.out.println("The sum is " + sum); /* 9*/ } /* 10*/ }
b04a001@AsiaA1:~/comp2b% java ArraySummation The sum is 900 b04a001@AsiaA1:~/comp2b%
次の例は、配列要素の最大値を求めるものです。
{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("The maximum value is " + max); /* 12*/ } /* 13*/ }
b04a001@AsiaA1:~/comp2b% java ArrayMaximum The maximum value is 300 b04a001@AsiaA1:~/comp2b%
最後の例は、以下の長方形の総面積を計算するものです。
No. | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|
幅 | 20 | 50 | 40 | 10 | 60 |
高さ | 30 | 10 | 20 | 70 | 10 |
このような表で表されるデータは、配列を2つ用意し、添字を使って配列要素を結び付けるとうまく処理できます。 このように使われる配列を 並列配列 ( parallel array )とよびます。 この場合ですと、長方形の幅を配列 width に格納し、高さを配列 height に格納します。 すると、0番目の長方形は、幅 width [0], 高さ height [0], 1番目の長方形は、幅 width [1], 高さ height [1], ... となるわけです。
総面積を計算するには、 i 番目の長方形の面積 area を width [ i ] * height [ i ] で求め、 area の値を areaSum に足していきます。 プログラムは次の通りです。
/* 1*/ // 文字コード判定用コメント /* 2*/ class RectangleArea { /* 3*/ public static void main (String[] args) { /* 4*/ int i, area, areaSum = 0; /* 5*/ int[] width = {20, 50, 40, 10, 60}; /* 6*/ int[] height = {30, 10, 20, 70, 10}; /* 7*/ System.out.println("No.\tWidth\tHeight\tArea"); /* 8*/ for (i = 0; i < width.length; i++) { /* 9*/ area = width[i] * height[i]; /* 10*/ areaSum = areaSum + area; /* 11*/ System.out.print(i + "\t"); /* 12*/ System.out.print(width[i] + "\t"); /* 13*/ System.out.print(height[i] + "\t"); /* 14*/ System.out.println(area); /* 15*/ } /* 16*/ System.out.println("Total\t\t\t" + areaSum); /* 17*/ } /* 18*/ }
b04a001@AsiaA1:~/comp2b% java RectangleArea No. Width Height Area 0 20 30 600 1 50 10 500 2 40 20 800 3 10 70 700 4 60 10 600 Total 3200 b04a001@AsiaA1:~/comp2b%
ある小学校では、児童数が次の通りであるとします。
学年 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
児童数(男子) | 51 | 53 | 52 | 55 | 50 | 54 |
児童数(女子) | 50 | 55 | 51 | 52 | 53 | 54 |
このデータを配列 boy と girl に格納して、学年ごとの児童数と全校の児童数を計算します。 この計算のアルゴリズムを考え、プログラムを作成してください。 「0年生」を0人にして、1年生から計算と表示を行えば、うまくいきます。
b04a001@AsiaA1:~/comp2b% java ElementarySchool Grade Boy Girl Total 1 51 50 101 2 53 55 108 3 52 51 103 4 55 52 107 5 50 53 103 6 54 54 108 Total 630 b04a001@AsiaA1:~/comp2b%
余力のある人は、全校の男子児童数と女子児童数も計算してください。
b04a001@AsiaA1:~/comp2b% java ElementarySchool Grade Boy Girl Total 1 51 50 101 2 53 55 108 3 52 51 103 4 55 52 107 5 50 53 103 6 54 54 108 Total 315 315 630 b04a001@AsiaA1:~/comp2b%
今日の演習6の答案(Javaプログラム)を、メールでkonishi@twcu.ac.jp宛に提出してください。 メールを送るときは、大学のパソコンを使うか、大学のメール・サーバに接続するかして、差出人が大学のメール・アドレスになるようにしてください。 メールの本文には、学生番号、氏名、科目名、授業日(6月2日)を明記してください。