プログラムの基本形は、文を並べたものです。 このようなプログラムを実行しますと、コンピュータは文の順序に従って動きます。 コンピュータの動きを変えるには、 制御構造 ( control structure )を利用します。 制御構造を表す文には、条件文や繰返し文などがあります。
条件文
(
conditional statement
)は、条件が成り立つかどうかによって実行する文が変わるものです。
基本的な条件文には、
if
文と
if
-
else
文があります。
if
文
の形式は
if (条件式) { 文の並び }
です。
これで、条件式の値が
true
ならば文の並びが実行されます。
if
-else
文
の形式は
if (条件式) { 文の並び1 } else { 文の並び2 }
です。
これで、条件式の値が
true
ならば文の並び1が実行され、
false
ならば文の並び2が実行されます。
if
-
else
文を多重にするには、
if (条件式1) { 文の並び1 } else if (条件式2) { 文の並び2 } else { 文の並び3 }
のように書きます。
「もし式の値が1ならば何々をし、2ならば何々をし、…」という制御構造は、それなりに使われます。
Java言語では、このような構造のために、
switch
文が用意されています。
switch
文
は、
case
文
を伴い、次のように書きます。
switch (整数式) { case 整数1: 文の並び1 break; ... default: 文の並び* break; }
これで、整数式の値が整数1ならば文の並び1が実行され、…、どれでもないならば文の並び*が実行されます。
1つの
switch
文の中の
case
文は、整数がすべて異なるようにします。
また、
case
文の並びの最後には、どれでもない場合を表す
default
を書きます。
それぞれの
case
文の最後には、
break
を書きます。
例えば、配列に格納されたゴルフのスコアを、数ではなく「パー」や「バーディー」のように出力するプログラムは、次のようになります。
/* 1*/ class SwitchTest { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ int[] a = {0, 2, -2, 4, 1, 1, 3, 0, -1}; /* 5*/ for (i = 0; i < a.length; i++) { /* 6*/ switch (a[i]) { /* 7*/ case -2: System.out.println("Eagle"); break; /* 8*/ case -1: System.out.println("Birdie"); break; /* 9*/ case 0: System.out.println("Par"); break; /* 10*/ case 1: System.out.println("Bogey"); break; /* 11*/ case 2: System.out.println("Double bogey"); break; /* 12*/ case 3: System.out.println("Triple bogey"); break; /* 13*/ default: System.out.println(a[i]); break; /* 14*/ } /* 15*/ } /* 16*/ } /* 17*/ }
b04a001@AsiaA1:~/comp3b% java SwitchTest Par Double bogey Eagle 4 Bogey Bogey Triple bogey Par Birdie b04a001@AsiaA1:~/comp3b%
もちろん、
switch
文を使わなくても、
if
-
else
文を使えば同じことができます。
ただし、プログラムは多少長くなります。
以下のプログラム(部分)と比較してください。
if (a[i] == -2) { System.out.println("Eagle"); } else if (a[i] == -1) { ... } else { System.out.println(a[i]); }
繰返し文
(
repetitive statement
)
は、文を何度か繰り返し実行するものです。
繰返しは
ループ
(
loop
)
とも呼ばれます。
基本的な繰返し文には、
while
文と
for
文があります。
while
文
の形式は
while (条件式) { 文の並び }
です。
これで、条件式の値が
true
である限り、文の並びが繰り返し実行されます。
for
文
の形式は
for (文1; 条件式; 文2) { 文の並び }
です。 これは、
文1 while (条件式) { 文の並び 文2 }
と同じ意味です。
while
文と似たものに、
do
-
while
文があります。
これは、条件式を確認してから文の並びを実行するのではなく、文の並びを実行してから条件式を確認するものです。
do
-while
文
の形式は、次の通りです。
do { 文の並び } while (条件式);
これは、
文の並び while (条件式) { 文の並び }
と同じ意味です。
while
文がその中身を一度も実行しないかもしれないのに対して、
do
-
while
文はその中身を必ず一度は実行します。
条件式の値に関わらず、1回以上繰り返す場合は、
do
-
while
文を使います。
例えば、長さが0ではない配列の要素を出力するプログラムは、次のように書けます。 ただし、配列の長さが0の場合はエラーになりますので、あまりよいプログラムではありません。
/* 1*/ class DoWhileTest { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ int[] a = {10, 20, 30, 40, 50}; /* 5*/ i = 0; /* 6*/ do { /* 7*/ System.out.println(a[i]); /* 8*/ i++; /* 9*/ } while (i < a.length); /* 10*/ } /* 11*/ }
b04a001@AsiaA1:~/comp3b% java DoWhileTest 10 20 30 40 50 b04a001@AsiaA1:~/comp3b%
プログラムの文を順番に実行せず、他の所に移動する制御のことを、 分岐 ( branch ) または ジャンプ ( jump ) と言います。
例えば、
return
文
は分岐文の一種です。
メソッドの実行中に
return
文がありますと、メソッドの途中でも実行が終了し、呼出し側に制御が戻ります。
break
文
は、繰返しを終了する分岐文です。
具体的には、繰返し文
while
,
do
-
while
,
for
の実行中に
break
文がありますと、繰返しの途中でも実行が終了し、繰返し文の次に制御が移ります。
break
文は、例えば要素の探索に役立ちます。
配列の中に0以外の数があるかどうかを確認する場合、もし0以外の数が見つかったら、残りの要素を確認する必要はありません。
そこで、
for
文を用いて配列要素を一つずつ確認し、もし0以外の数だったら、
break
文で繰返しを終了するというプログラムが書けます。
/* 1*/ class BreakTest { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ int[] a = {0, 0, 0, 40, 0}; /* 5*/ for (i = 0; i < a.length; i++) { /* 6*/ if (a[i] != 0) { /* 7*/ break; /* 8*/ } /* 9*/ } /* 10*/ if (i < a.length) { /* 11*/ System.out.println("Found."); /* 12*/ } else { /* 13*/ System.out.println("Not found."); /* 14*/ } /* 15*/ } /* 16*/ }
b04a001@AsiaA1:~/comp3b% java BreakTest Found. b04a001@AsiaA1:~/comp3b%
break
文を利用した場合、(見つからなくて)条件式で繰返しが終了したのか、(見つかって)
break
文で繰返しが終了したのかが分かりません。
上記のプログラムでは、ループ制御変数
i
が配列の途中を指しているかどうかで判定しています。
以下のプログラムでは、論理型の変数
found
を用意し、見つかったら
found
の値を変えることで区別します。
/* 1*/ class BreakTest2 { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ int[] a = {0, 0, 0, 40, 0}; /* 5*/ boolean found = false; /* 6*/ for (i = 0; i < a.length; i++) { /* 7*/ if (a[i] != 0) { /* 8*/ found = true; /* 9*/ break; /* 10*/ } /* 11*/ } /* 12*/ if (found) { /* 13*/ System.out.println("Found."); /* 14*/ } else { /* 15*/ System.out.println("Not found."); /* 16*/ } /* 17*/ } /* 18*/ }
continue
文
は、繰返しを完全に終了するのではなく、繰返しを一回だけ終了する分岐文です。
具体的には、繰返し文
while
,
do
-
while
,
for
の実行中に
continue
文がありますと、繰返しの途中でもその回が終了し、次の回のために繰返し文の条件式に制御が移ります。
continue
文は、例えば一部の要素を無視するときに役立ちます。
配列の要素を出力するが、0は無視する場合、もし0が見つかったら、それに対する処理は必要はありません。
このことを
continue
文で表しますと、次のようになります。
/* 1*/ class ContinueTest { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ int[] a = {10, 20, 30, 0, 50}; /* 5*/ for (i = 0; i < a.length; i++) { /* 6*/ if (a[i] == 0) { /* 7*/ continue; /* 8*/ } /* 9*/ System.out.println(a[i]); /* 10*/ } /* 11*/ } /* 12*/ }
b04a001@AsiaA1:~/comp3b% java ContinueTest 10 20 30 50 b04a001@AsiaA1:~/comp3b%
繰返しの繰返し、すなわち、繰返し文の中にさらに繰返し文を書くこともできます。 このような制御構造を、2重ループと呼ぶことがあります。 3重ループやそれ以上も考えられます。
一般的に、2重ループではループ制御変数を2つ用意します。 変数が i と j ならば、 i を外側のループ制御変数とし、 j を内側のループ制御変数とします。
次のプログラムは、出力を4回繰り返すことを3回繰り返すものです。 変数 i と j がどのように変化するかを見てください。
/* 1*/ class DoubleLoop { /* 2*/ public static void main (String[] args) { /* 3*/ int i, j; /* 4*/ for (i = 0; i < 3; i++) { /* 5*/ for (j = 0; j < 4; j++) { /* 6*/ System.out.println("i = " + i + ", j = " + j + "."); /* 7*/ } /* 8*/ } /* 9*/ } /* 10*/ }
b04a001@AsiaA1:~/comp3b% java DoubleLoop i = 0, j = 0. i = 0, j = 1. i = 0, j = 2. i = 0, j = 3. i = 1, j = 0. i = 1, j = 1. i = 1, j = 2. i = 1, j = 3. i = 2, j = 0. i = 2, j = 1. i = 2, j = 2. i = 2, j = 3. b04a001@AsiaA1:~/comp3b%
2重ループでは、内側の繰返しの回数を変えることもできます。 次のプログラムでは、出力を0回繰り返し、1回繰り返し、…としています。
/* 1*/ class TriangleLoop { /* 2*/ public static void main (String[] args) { /* 3*/ int i, j; /* 4*/ for (i = 0; i < 5; i++) { /* 5*/ for (j = 0; j < i; j++) { /* 6*/ System.out.println("i = " + i + ", j = " + j + "."); /* 7*/ } /* 8*/ } /* 9*/ } /* 10*/ }
b04a001@AsiaA1:~/comp3b% java TriangleLoop i = 1, j = 0. i = 2, j = 0. i = 2, j = 1. i = 3, j = 0. i = 3, j = 1. i = 3, j = 2. i = 4, j = 0. i = 4, j = 1. i = 4, j = 2. i = 4, j = 3. b04a001@AsiaA1:~/comp3b%
2重ループの例として、与えられた配列の中から重複を取り除き、一つだけ残すという処理を考えます。 ここで、0はデータ無しを意味するものとします。 重複の中で残すのは最も左の要素とします。
プログラムの方針は、 a [ i ]にデータがあれば、それより右の要素 a [ j ]に対して、 a [ i ]と等しければ a [ j ]に0を格納する、ということを、 i を0, 1, ...として繰り返すというものです。 プログラムの動作を確認するために、途中で配列の要素を出力しています。
/* 1*/ class LeaveOnlyOne { /* 2*/ public static void main (String[] args) { /* 3*/ int i, j; /* 4*/ int[] a = {1, 1, 2, 1, 2, 3, 4, 3, 5}; /* 5*/ for (i = 0; i < a.length; i++) { /* 6*/ if (a[i] != 0) { /* 7*/ for (j = i + 1; j < a.length; j++) { /* 8*/ if (a[j] == a[i]) { /* 9*/ a[j] = 0; /* 10*/ } /* 11*/ } /* 12*/ } /* 13*/ for (j = 0; j < a.length; j++) { /* 14*/ System.out.print(" " + a[j]); /* 15*/ } /* 16*/ System.out.println(); /* 17*/ } /* 18*/ } /* 19*/ }
b04a001@AsiaA1:~/comp3b% java LeaveOnlyOne 1 0 2 0 2 3 4 3 5 1 0 2 0 2 3 4 3 5 1 0 2 0 0 3 4 3 5 1 0 2 0 0 3 4 3 5 1 0 2 0 0 3 4 3 5 1 0 2 0 0 3 4 0 5 1 0 2 0 0 3 4 0 5 1 0 2 0 0 3 4 0 5 1 0 2 0 0 3 4 0 5 b04a001@AsiaA1:~/comp3b%
与えられた配列
の0でない要素を、順序を変えずに左に詰めるプログラムを作成してください。 プログラムの方針は、 a [ i ]が0ならば、それより右に0でない要素があるかどうかを調べ、もしあればその最も左の要素 a [ j ]の値を a [ i ]に格納し、 a [ j ]には0を格納する、ということを、 i を0, 1, ...として繰り返すというものです。 プログラムの動作を確認するために、途中で配列の要素を出力してください。
b04a001@AsiaA1:~/comp3b% java StuffToLeft 1 0 2 0 0 3 4 0 5 1 2 0 0 0 3 4 0 5 1 2 3 0 0 0 4 0 5 1 2 3 4 0 0 0 0 5 1 2 3 4 5 0 0 0 0 1 2 3 4 5 0 0 0 0 1 2 3 4 5 0 0 0 0 1 2 3 4 5 0 0 0 0 1 2 3 4 5 0 0 0 0 b04a001@AsiaA1:~/comp3b%
余力のある人は、左ではなく右に詰めるプログラムも作成してください。
b04a001@AsiaA1:~/comp3b% java StuffToRight 1 0 2 0 0 3 4 0 5 1 0 2 0 0 3 0 4 5 1 0 2 0 0 0 3 4 5 1 0 0 0 0 2 3 4 5 0 0 0 0 1 2 3 4 5 0 0 0 0 1 2 3 4 5 0 0 0 0 1 2 3 4 5 0 0 0 0 1 2 3 4 5 0 0 0 0 1 2 3 4 5 b04a001@AsiaA1:~/comp3b%
今日の演習2の答案(Javaプログラム)をメールで提出してください。 差出人は学内のメール・アドレス(b04a001@cis.twcu.ac.jpなど)とし、宛先はkonishi@cis.twcu.ac.jpとします。 メールの本文には、学生番号、氏名、科目名、授業日(10月5日)を明記してください。