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

コンピュータ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ではない配列の要素を出力するプログラムは、次のように書けます。

/*  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つ用意します。 変数が 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.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@twcu.ac.jpなど)とし、メールの宛先はkonishi@twcu.ac.jpとします。 メールの本文には、学生番号、氏名、科目名、授業日(10月6日)を明記してください。


2.8 参考文献


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

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