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

コンピュータIIIB(Javaアルゴリズム)第2回

目次
2.1 制御構造
2.2 条件文
2.2.1 基本的な条件文
2.2.2 switch文
2.3 繰返し文
2.3.1 基本的な繰返し文
2.3.2 do-while文
2.4 分岐文
2.4.1 分岐とは
2.4.2 break文
2.4.3 continue文
2.5 2重ループ
2.5.1 2重ループとは
2.5.2 2重ループの例
2.6 演習2
2.7 レポート課題
2.8 参考文献
索引
break文   case文   continue文   do-while文   for文   if-else文   if文   return文   switch文   while文   繰返し文   ジャンプ   条件文   制御構造   分岐   ループ  

2.1 制御構造

プログラムの基本形は、文を並べたものです。 このようなプログラムを実行しますと、コンピュータは文の順序に従って動きます。 コンピュータの動きを変えるには、 制御構造control structure )を利用します。 制御構造を表す文には、条件文や繰返し文などがあります。


2.2 条件文

2.2.1 基本的な条件文

条件文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
}

のように書きます。

2.2.2 switch文

「もし式の値が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]);
}

2.3 繰返し文

2.3.1 基本的な繰返し文

繰返し文repetitive statement ) は、文を何度か繰り返し実行するものです。 繰返しは ループloop ) とも呼ばれます。 基本的な繰返し文には、 while 文と for 文があります。

while の形式は

while (条件式) {
    文の並び
}

です。 これで、条件式の値が true である限り、文の並びが繰り返し実行されます。

for の形式は

for (文1; 条件式; 文2) {
    文の並び
}

です。 これは、

文1
while (条件式) {
    文の並び
    文2
}

と同じ意味です。

2.3.2 do-while文

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%

2.4 分岐文

2.4.1 分岐とは

プログラムの文を順番に実行せず、他の所に移動する制御のことを、 分岐branch ) または ジャンプjump ) と言います。

例えば、 return は分岐文の一種です。 メソッドの実行中に return 文がありますと、メソッドの途中でも実行が終了し、呼出し側に制御が戻ります。

2.4.2 break文

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*/ }

2.4.3 continue文

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.5 2重ループ

2.5.1 2重ループとは

繰返しの繰返し、すなわち、繰返し文の中にさらに繰返し文を書くこともできます。 このような制御構造を、2重ループと呼ぶことがあります。 3重ループやそれ以上も考えられます。

一般的に、2重ループではループ制御変数を2つ用意します。 変数が ij ならば、 i を外側のループ制御変数とし、 j を内側のループ制御変数とします。

次のプログラムは、出力を4回繰り返すことを3回繰り返すものです。 変数 ij がどのように変化するかを見てください。

/*  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.5.2 2重ループの例

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%

2.6 演習2

与えられた配列

{1, 0, 2, 0, 0, 3, 4, 0, 5}

の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.7 レポート課題

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


2.8 参考文献


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

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