Lecture 4 制御文2

この章では,さらに複雑なifの構文,ループ,ループの脱出と継続, switch文などについて学びます.これらが自由にできるようになると, 様々なプログラムを作ることができるようになります.

if文のネスト.高度で複雑なif文

if文が別のifやelseの中に入っている時,「外側のifにネストされたif」とか,「入れ子になったif」などと呼ぶ.
if(class==5 || class==6){
    printf("機械工学科の学生です.");
    if(class==5)
        printf("教室は0609です.");
    else if(class==6)
        printf("教室は0603です.");
}

一般的な形式は以下のようになる.
if(式) 文;
else
    if(式) 文;
    else
        if(式) 文;
        ....
        else 文;
このように,if...elseのはしごか階段のようになっているので,if-else-if ladderとか,if-else-if staircaseなどと呼ばれる.式は上から下に順に実行(評価)されていく.
真の式が見つかった場合,対応する文が実行され,その後の式は飛び越されて実行されなくなる. 真の式が見つからない場合,最後のelse文が実行されるが,else文が存在しない場合は何も実行されない.

if-else-ifの階層が深くなると,判読が難しくなるため,一般には以下の形式を取る.
    if(式) 文;
    else if(式) 文;
    else if(式) 文;
    else if(式) 文;
    ...
    else 文;

forループ

既に例で示したように,C言語で最もよく利用されるループ(繰り返し計算)には,for を用いる.forの構文は,
for(初期設定部; 条件判定部; インクリメント部)文;
であったが,それぞれの部分には対応する式を書いてもいいし,じつは何も書かなくてもエラーにならない.各部は自由に使うことができる.
int i=0;  // 初期化を外でしても良い.
for(  ;  ;  ){  // 各部に何も書かなくてもエラーにはならない.
    if(i++>10) ...; // 別の場所で判定やインクリメントをしても良い.
}
この様に書式に大きな柔軟性のある forループであるが,forのカッコの中にまとめて書くことで諸条件がわかりやすく,見通しやすくなるという面もあるため,後々のデバッグの便を考えて慣例に則った(for(int i=0; i<n; i++){ のような)書き方をすることを勧める.

whileループ,doループ

for以外にも,whileを使ったループがある.
while(式) 文;
whileループは,式が真である間,文の実行が繰り返され,式が偽になると終了する.式の値は,文が実行される前に評価される. つまり,最初から式が偽であれば,文は一度も実行されないことになる.

このwhileループとは対照的に,do ... while ループは,式の評価はループの中の文を実行した後に行う. 従って,仮に式が最初から偽であったとしても,文は必ず一回は実行されることになる.
do {
    文;
} while(式);

ループのネスト(多重ループ)

ループの中にループがあるとき,ネストされたループと呼ぶ.例えば以下の例は,行と列の繰り返しの回数をそれぞれのforループで制御することによって,画面に三角形をプリントする.
for(int line=0; line<10; line++){
    for(int column=0; column<line+1; column++){
        printf("@");
    }
    printf("\n");
}

breakによるループの脱出

break文は大変便利なもので,終了判定式を待たずにいつでもループから脱出できる.ループの内側で,break文を実行するとループをすぐに終了し,ループの外の次の文に処理が移行される.
以下は,i が11になるとループを終了し,printf文は12回しか実行されない.
for(int i=0; i<1000000; i++){
    printf("%d\n",i);
    if(i>10) break;		// i が 10より大きくなると,
}
// ループを抜けだしてここまでジャンプ.

continueによるループのスキップ

ループを抜け出したくはないが,ある条件ではその回の処理をしたくないこともある.この様なとき continue文を用いる. 例えば以下の例では,i が10の倍数(つまり i = 10, 20, 30, ...)の時だけプリントされる.
for(int i=0; i<=100; i++){
    if(i%10) continue;	// 10で割り切れない時に真となり,
    printf("%d\n",i);
}		// } の内側までスキップしてきて,またforの次の回に続く.

switch文

switchはループではなく,ifなどの条件文の仲間である.if-elseをたくさん用いると,多数の分岐をさばくことができるが,非常に見難くなることが多い.switch文を用いると,多数の分岐をすっきりと記述することができる.
switch(変数){	// この変数に置けるのは整数(int, char)のみ.
    case 定数1:// 変数が定数1なら,ここから次のbreakまで実行される.
        文;
        break;
    case 定数2:// 変数が定数2なら,ここから次のbreakまで実行される.
    	文;
    	break;
    case ...:	// caseは何個でも入れることができる.
        ...
    default:	// 上の条件にどれも当てはまらない場合,ここが実行される.
        文;
    	break;
}
  • defaultは無くてもよい.
  • 当てはまるものが何もなければ何も実行されない.
  • switchで記述できるものは,if...elseでも記述できる.しかしその逆は常に真ではない. if...elseはどのような条件式を混ぜて使えるのに対して,switchが評価できるのは整数だけである.
  • switchをネストすることもできる.
  • breakはなくてもエラーにはならない.

switchで複数のcaseにまたがる処理を書く

switchでは,breakを書かなくてもエラーにはならず,合致していないはずの次のcaseの処理を行ってしまう.この性質を利用して,複数のcaseに対応する処理を書くことができる. 以下の例では,変数 x が 1,2,3の場合に文1を,x=4,5,6の場合に文2を実行する.また,文aはx=4の時だけ実行され,文bはx=4,5の時にも実行される.つまり,x=4であるときは,文a,文b,文2の3つが実行される.
switch(x){
    case 1:
    case 2:
    case 3:
    	文1;	// x=1,2,3の時に実行される
    	break;

    case 4:
    	文a;	// x=4の時のみ実行される
    case 5:
    	文b;	// x=4,5の時に実行される
    case 6:
    	文2;	// x=4,5,6の時に実行される
    	break;
}
※注:defaultが無いので,1,2,3, 4,5,6 以外のケースでは何も実行されない.

禁断のgoto文

C言語では,goto文という,指定したラベルの位置にジャンプする機能を持つ「無条件」分岐構文も備えている. しかし,goto文を用いるとプログラムの構造が破壊され,どのような処理が行われているのか理解し難いプログラムになる. また,goto文を用いなければ実現不可能な処理は存在しないことがわかっている. 従って,ここでは goto文が存在することは示すが,goto文の構文を解説することはしない. goto文は百害あって一利なしであり,決して用いないこと.

Quiz 4(第4回の提出課題ではありません)

以下の問それぞれに対応するプログラムを作成しなさい.


    1. while文を用いて以下の式を満たす整数Aを求めよ.
        10(A+3)-(7-3A) = 1622

      【ヒント】式変形をせずにそのままプログラムします. Aの値を変えながら計算し,右辺の数値と等しいかどうかを調べます(=力技)
      【ヒント】Aの範囲は±10,000にあるとして計算して良いです.
      【ヒント】手計算でAを求めて,プログラムが合っているかどうか確認しよう.


    2. キーボードより数値を繰り返し入力し,0が入力されたら入力をやめて, それまで入力した数値の平均値を表示するプログラムを作成せよ.

      【ヒント】数値が入力される度に0かどうか調べる.
      【ヒント】0でなければ①合計を求め,②入力回数を数える.
      【ヒント】0だったら,①/②を計算し,表示して終わる.


    3. 1~99までの値を表示しなさい.ただし,3の倍数のときだけ【カッコ】書きで表示すること.

      【ヒント】3の倍数とは「3で割った余りが0になる数字」です。


    4. キーボードから金利(年率)をパーセントで(3%のときは3)入力し,元本が2倍になる(つまり複利計算ですね)のは何年後かを調べるプログラムを作成しなさい. 計算には while, breakを必ず使用せよ.

    5. for文を2つ使って,九九の表を作ってみよう.



Quizのヒント

スクラッチで書いたプログラムの例です。これを理解できたらC言語に書き換えてみましょう。

Q4-2


Q4-3


Q4-4



【ヒント】Scratchにはbreak文に相当するコマンドが無いようなので、 ここでは「このスクリプトを止める」というコマンドを用いています。 C言語の場合は、break文を用いてループから脱出してから、ループの外で処理をした方が良いと思います。


Quizのこたえ(あくまで一例です)

C言語で書いたプログラムの例です.Scratchのコードと比べてみよう.

Q4-1


Q4-2


【ヒント】コンパイル時に,bcc32 (g++) -DDEBUG q4-2.cpp などとするとデバッグオプションが生きます.

Q4-3


Q4-4





Assignment 4(第4回の宿題)

課題の提出は Online Judge にて行います.

  • 提出期限があります.できるだけ早めにやりましょう.
  • Online Judge は普通の課題提出方法とは異なり,良い点が取れるまで何度でも挑戦できます.良い点が取れるまで頑張ってやろう.
  • わからないことは,早めに Teams で聞こう.問題は自分で解決すること.
  • それでもどうしてもわからないときは,毎週月曜日の2時限目にZoomによるオフィスアワーを用意しています. ZoomのリンクはOh-o! meijiで確認してください.
  • Online Judge のページはこちら