Fujitsu The Possibilities are Infinite

 

COBOL技術者のためのJava言語入門
3章:制御文

[索引]  if文 |  for文 |  while文 |  do-while文 |  switch文 |  その他 

制御文は処理の流れを変更するものです。 ここで述べる制御文の多くはダイクストラが提唱した構造化プログラミングの考えに基づいて構成されたものです。 gotoレス、例外処理などとともに、最近の多くのプログラミング言語で採用されています。 各制御文には固有の構造があります。 以下に主な制御文の機能とその構造を示します。

if文

if文の構造

        if (条件) {        
            文
        } else {
            文
        }

機能は見ただけで理解していただけると思います。 条件にはboolean型の式を入れます。 中括弧 { } の位置が特徴的ですが、これは構造を見やすくするための工夫で、Javaの言語仕様で定めているものではありません。 中括弧始め { を行頭に置く流儀もありますが、最近は上記のスタイルを使う人が多いようです。

※ COBOLのif文では then や endif などのキーワードでブロックの区切りを表していました。 これは英語としての自然さを狙ったと考えられますが、Javaでは見た目や書く手間を重視し括弧を活用しています。

以下は a が偶数なら b に "even" を、奇数なら "odd" をセットする例です。

        if (a % 2 == 0) {
            b = "even";
        } else {
            b = "odd";
        }

省略形

else以下は省略可能です。 また上の例のように文が1つしかないときは、中括弧も省略して次のように記述することもできます。

        if (a % 2 == 0) b = "even";
        else b = "odd";

if文が多重に使われるときにelse句を省略すると if と else との対応が曖昧になりがちですが「elseは直近の(elseを従えていない)ifに対応する」というルールに従います。

else if形式

次のようにelse if文を繰り返す形式も可能です。 この構造では複数の条件が満たされても最初に満たした条件に対応する文しか実行されません。

        if (条件1) {
            文A
        } else if (条件2) {
            文B
            …
        } else if (条件n) {
            文Y
        } else {
            文Z
        }

【確認問題】 3.1

int型の変数 nen に年(西暦)が格納されています。 以下のルールにしたがって、うるう年か否かを判定し、boolean型の変数 leap にtrue(うるう年)またはfalse(平年)をセットしてください。
(ヒント) 割り切れるかどうかの判定は剰余演算子( % )を使います。

  ルール:(1) 4で割り切れればうるう年
          (2) ただし100で割り切れれば平年
          (3) ただし400で割り切れればうるう年

for文

for文の構造

        for (初期化; 条件; 値の更新) {        
            文
        }

★ for文は繰り返し処理時によく使う機能を備えた巧妙な構造になっています。 上記のfor文は次のように実行されます。

(1) 初期化の実施
(2) 条件の判定→条件が否定されたらfor文から抜ける
(3) 文の実行
(4) 値の更新の実施
以降(2)~(4)の繰り返し。

以下は1から10までの数の足し算をするプログラムの例です。

        int i,sum=0;
        for (i=1; i<=10; i++) {
            sum = sum + i;
        }

※ ここで「条件が真の間だけ繰り返す」ことに注意してください。 COBOLで書くと

        PERFORM WITH TEST BEFORE VARYING VAL FROM 1 BY 1 UNTIL VAL > 10

となり条件のロジックが逆の関係になります。

for文内での変数の型宣言

次の例のようにループで使う変数をfor文の ( ) の中で型宣言することができます。 このようにするとこの変数 i はfor文の構造の中だけで有効です。 すなわちfor文の外部で i という変数を使っていてもそれとは無関係にローカルな変数として i が利用できるわけです。

        for (int i=0; i<10; i++)        // intをここで書くとローカル変数

記述の自由度

for文の ( ) の中の式は同じ変数を使う必要はありません。 プログラムとして間違っていなければどんなものを書いてもかまいません(理解しづらくなり保守性は下がるかもしれませんが)。 また記述を省略したり、逆に複数の命令を書いてもかまいません。

        for (i=0; a!=0; b++)    // このようなものでも可
        for (; i<10; )  // 初期化済で値の更新は{ }内でやるならこれでも可
        for (i=0,j=10; i<10; i++,j--)   // 複数の処理を書いても可

【確認問題】 3.2

int型の2次元配列 a[10][20] を宣言して、その全要素に 0 をセットする命令を書いてください。
(ヒント) for文を2重に使います。

while文

while文の構造

        while (条件) {        
            文
        }

while文も繰り返し処理を行うときに使います。 上記のwhile文は次のように実行されます。 最初に判定を行うので、文が一度も実行されないこともあります。

(1) 条件の判定→条件が否定されたらwhile文から抜ける
(2) 文の実行
以降(1)~(2)の繰り返し。

1~10の足し算のプログラムをwhile文を使って書くと次のようになります。 この例では i を減算して行きますが、もちろん加算しても結構です。

        int i=10, sum=0;
        while (i>0) {
          sum = sum + i;
          i--;
        }

※ ここでも「条件が真の間だけ繰り返し」ます。 COBOLでは以下のように逆です。

        PERFORM WITH TEST BEFORE UNTIL VAL = 0

英語のwhile(~の間じゅう)とUNTIL(~になるまで)の差ですね。

★ while(true) と書いて無限ループとし、{ } ブロックの中で、後述のbreak文を書いてループから抜けるパターンも良く使われます。 この場合にC言語ではtrue値として 1 を使い while(1) と書きましたが、Javaでは true と書かねばならないので注意してください。


【確認問題】 3.3

上の例の1~10の足し算を、変数 i を加算するやり方に変えてください。

do-while文

do-while文の構造

        do{
            文
        } while (条件);        

do-while文はwhile文と似ていますが、文が必ず1回は実行されるところが異なります。 上記の構造のdo-while文は次のように実行されます。

(1) 文の実行
(2) 条件の判定→条件が否定されたらwhile文から抜ける
以降(1)~(2)の繰り返し。

足し算のプログラムをdo-while文で書くと次のようになります。

        int i=10, sum=0;
        do{
          sum = sum + i;
          i--;
        } while (i>0);

switch文

switch文の構造

        switch (評価式) {        
        case 定数:
            文
            break;
        case 定数:
            文
            break;
            …
        default:
            文
        }

switch文では評価式の値に基づいて、値が一致する定数を持つcaseラベルへジャンプします。 その後、break文に出会うか、switchブロックの最後になるまで処理を継続します。 各case文の最後にはbreak文を書くのが普通ですが、もしbreak文がないと、次のcaseラベル以降の内容も引き続いて実行します。 式の評価値がどのcaseの定数とも一致しないときは、defaultラベルが書かれているとその部分を実行します。

★ 評価式と定数はbyte、char、short、int型のいずれかでなくてはなりません。 以下にswitch文の例を示します。

        switch (score) {
        case 3:
          System.out.print("たいへん");         // 印刷文(改行なし)
        case 2:
          System.out.println("良くできました"); // 印刷文(改行あり)
          break;
        case 1:
          System.out.println("普通です");
          break;
        default:
          System.out.println("評価できません");
        }

印刷文が初めて出てきました。 この書き方を覚えてください。 単にprintと書くと ( ) の内容を印刷するだけですが、printlnとすると、印刷後改行します。 lnはlineの略です。
上の例ではscoreの値により、3→"たいへん良くできました"、2→"良くできました"、1→"普通です"、それ以外→"評価できません" が印刷されます。

※ この例はbreak文省略時の動作説明のために多少無理して作ったもので、このような作り方を推奨するものではありません。 普通はcase3の場合にもちゃんと全文を書いてbreak文を入れた方が良いでしょう。 break文を書かないときは、その理由をコメントにしておくと保守が楽です。


【確認問題】 3.4

long型の変数はswitch文の評価値として使えるか答えてください。

その他

Javaにはgoto文が無いので、以下の文でプログラムの処理の流れを制御します。

break文 ★

break文はfor、while、doなどのループから脱出するときに使用します。 ループが多重になっている時は一つ外のループに抜けます。 while文にラベルをつけ、break文でそのラベル名を指定すると多重ループの中にいても、ラベルをつけたwhile文の外に出られます。

continue文 ★

continue文はやはりループの中で用いられます。 continue文があるとループの終端までスキップします。 for文なら更新の実行から、while文なら条件の判定から続行します。 次の回以降のループ処理は普通に実行されます。

※ COBOLではCONTINUEは「何もしない」ですが、Javaでは積極的な意味を果たします。

return文

return文はメソッド(サブルーチン:次章で説明)から抜け出るときに使います。 普通はメソッドの最後に記述しますが、途中に記述すると、そこで処理を打ち切りメソッドから抜けます。 return文の直後に式を書くことができます。 式があるとその値をメソッドの呼び出し元に返します。


【確認問題】 3.5

次のプログラムを実行すると何が出力されますか。

        int i=5;
        while (i>0) {
          i--;
          if (i==3) continue;
          System.out.print(i);
        }