C++言語解説:1-3.プログラム制御文
2002-08-15

[概要] 構造化プログラミングの基礎となる選択/反復の記述法について、if文、for文、
    switch文、while文、do-while文、continue文、break文、そしてgoto文について
    学習します。

[構成]・if文
     * if文の構成
     * else-if文
   ・switch文
   ・forループ
     * for文によるループ
     * 制御式の省略
   ・whileループ
     * while文によるループ
     * do-while文によるループ
   ・その他
     * continue文
     * breka文
     * goto文


if文

 if文の構成
 
  ・C/C++で選択(selection statement)を実行する文がif文です。以下の形式で記述さ
   れます。
     if(条件式) {・・・}
     else {・・・}
   if又はelseの指す実行内容が単一ステートメントで記述できるものであればブロッ
   ク記述の必要はありません(*1)
  
  ・ifは条件式(conditional expression)を評価し、結果がtrueならばifの指すブロッ
   クが実行されます。結果がfalseならばelseの指すブロックが実行されます。
当然
   trueとfalseの解釈には前章で説明した暗黙の型変換(bool,int)が適用されます。

   [List1.if文の例]
   ┌───────────────────────────────────┐
    #include <iostream>
    using namespace std;
    
    int main()
    {
      int i_a = 20;
      
      if (i_a > 10) {
        cout << "10未満です";
      }
      else {
        cout << "10以上です";
      }
      
      return 0;
    }
   └───────────────────────────────────┘
   ┌───────────────────────────────────┐
    [出力結果]
     10以上です
   └───────────────────────────────────┘
  
  ・if文は以下のようにネストすることができます。
     if(式1) {
       if(式2) {
         if(式3) {
           :
         }
       }
     }
     
  ・if文のネストは通常256階層まで許されていますが、実際はコンパイラや環境により
   異なりますし、プログラムの可読性が落ちるのでネストの階層は浅くするように努
   めるべきです。



 else-if文の構成
 
  ・elseは、if文をターゲットにすることができます。else-if文と呼ばれますが、この
   選択文は「複数条件を順番にチェックし、合致したところで実行」するときに利用
   します。

   [List1.else-if文の例]
   ┌───────────────────────────────────┐
    #include <iostream>
    using namespace std;
    
    int main()
    {
      int i_a = 20;
      
      if (i_a < 1) {
        cout << "1未満です";
      }
      else if (i_a < 5){
        cout << "1以上5未満です";
      }
      else if (i_a < 10){
        cout << "5以上10未満です";
      }
      else if (i_a < 20){
        cout << "10以上20未満です";
      }
      else if (i_a < 40){
        cout << "20以上40未満です";
      }
      else {
        cout << "40以上です";
      }
      
      return 0;
    }
   └───────────────────────────────────┘
   ┌───────────────────────────────────┐
    [出力結果]
     20以上40未満です
   └───────────────────────────────────┘


switch文

  ・先ほどelse-if文を見ましたが、条件式が「等式」である場合に限り使用できる複数
   条件選択文があります。それはswitch文です。
   ┌───────────────────────────────────┐
     switch(式) {
       case 定数1:
        : //実行内容1
       break;
       case 定数2:
        : //実行内容2
       break;
        :
       default:
        : //実行内容
     }
   └───────────────────────────────────┘
   
  ・switchで記述できる式は定数として「==」による比較ができる文字又は整数値に限
   られます。従ってfloatやdouble等の実数値を指定することはできません。
  
  ・式の値がcase文の指す定数と一致したところから文が実行され、break文まで続きま
   す。break文が無ければ、次のcase又はdefaultが示す内容を実行します。
   ┌───────────────────────────────────┐
    (1)break文がある場合     (2)break文が無い場合
     ┌────────────┐ ┌───────────────┐
     │case 定数1:       │ │case 定数1:          │
     │ :           │ │ :              │
     │ :  ↓        │ │ :              │
     │break; ┴→ switch抜ける│ │ :  ───┐        │
     │case 定数2:       │ │case 定数2: ↓次の実行文へ移る│
     │ :           │ │ :  ←──┘        │
     │ :           │ │ :              │
     │break;         │ │break;            │
     └────────────┘ └───────────────┘
   └───────────────────────────────────┘
  
  ・defaultは式の値がどのcaseとも一致しなかった場合又は上のcase文からの続きによ
   り実行されます。
 
   [List2.switch文の例]
   ┌───────────────────────────────────┐
    #include <iostream>
    using namespace std;
    
    int main()
    {
      int i_a = 20;
      
      switch(i_a){
        case 1:
          cout << "1です";
          break;
        case 5:
          cout << "5です";
          break;
        case 10:
          cout << "10です";
          break;
        case 20:
          cout << "20です";
          break;
        case 40:
          cout << "40です";
          break;
        default:
          cout << "40超です";
      }
      
      return 0;
    }
   └───────────────────────────────────┘
   ┌───────────────────────────────────┐
    [出力結果]
     20以上40未満です
   └───────────────────────────────────┘
  
  ・switch文中には16,384個のcaseを設定できることになっていますが、実行環境によ
   り異なることと、あまりにcaseが多いswitch文はエレガントさに欠けます。
  
  ・switch文をネストすることもできます。これもif文のネストと扱いは同様です。
  
  ・else-if文と比較してswitch文の方が実行速度が向上する傾向にあります。


for文

 for文によるループ
 
  ・C++ではループを形成する方法がいくつかあります。その一つであるfor文変数を
   介してループ実行を制御
します。よってfor文は以下の形式となります。
     for (初期値; 実行条件式; 変数処理){・・・}
  
  ・実行条件式がtrueであれば、変数処理を施した後、forの示すステートメントが実行
   されます。ステートメントが複数の場合はブロックとして記述します。
  
   [List3.for文の例]
   ┌───────────────────────────────────┐
    #include <iostream>
    using namespace std;
    
    int main()
    {
      int i_a;
      
      for (i_a = 0; i_a < 5; i_a++){
        cout << i_a << " ";
      }
      
      return 0;
    }
   └───────────────────────────────────┘
   ┌───────────────────────────────────┐
    [出力結果]
     0 1 2 3 4
   └───────────────────────────────────┘

  
 制御式の省略

  ・for文では制御に関する式を省略することができます。例えばList2では制御変数i_a
   をインクリメントしていますが、その制御を実行文中に持たせ、制御式からは省略
   することができます。
     (例) for(i_a=0; i_a<5; ){・・・}

  ・同様に全ての制御式を省略すると「無限ループ」を作ることができます。
     for(;;){・・・}
   この場合は実行文中で後述するbreakやgoto文を使用して無限ループを終了させます。


while文

 while文によるループ

  ・for以外にループを実行する文としてwhileがあります。whileは以下の形式です。
     while(式){・・・}
   while文は(式)がtrueの間実行を続けます。
  
  ・最初から式がtrueの場合、whileが指定するステートメントは一度も実行されないケ
   ースがあります。

   [List4.while文の例]
   ┌───────────────────────────────────┐
    #include <iostream>
    using namespace std;
    
    int main()
    {
      int i_a=0;
      
      while(i_a<10){
        cout << i_a;
        i_a++;
      }
      
      return 0;
    }
   └───────────────────────────────────┘
   ┌───────────────────────────────────┐
    [出力結果]
     0123456789
   └───────────────────────────────────┘
  
  ・whileの式がtrueの場合は実行をループ続けるので
     while(1){・・・}
   は無限ループとなります。これもforの無限ループと同様にbreakやgotoで制御を行
   います。


 do-while文によるループ
 
  ・for文やwhile文は最初に実行条件式を評価するため、状況によってはループ実行を1
   度も行わないケースがあります。
  
  ・状況によらず1度は実行したい場合、do-while文を使用します。
     do {
      : //実行分
     } while(式);


その他

 continue文
 
  ・forやwhile文のループ実行文中でcontinueを使用すると、実行を中断して条件式制
   御へ飛ぶ
ことができます。
     while  : 条件式評価へ
     do-while : 条件式評価へ
     for   : 変数処理へ(条件式評価ではない)
  
   [List5.continue文の例]
   ┌───────────────────────────────────┐
    #include <iostream>
    using namespace std;
    
    int main()
    {
      int i_a;
      
      for (i_a=0; i_a<10; i_a++){
        if (i_a == 5) continue;
        cout << i_a;
      }
      
      return 0;
    }
   └───────────────────────────────────┘
   ┌───────────────────────────────────┐
    [出力結果]
     012346789
   └───────────────────────────────────┘


 break文
 
  ・break文はループ実行を終了し、for又はwhile/do-whileに続く行へ実行を移します。
  
   [List6.break文の例]
   ┌───────────────────────────────────┐
    #include <iostream>
    using namespace std;
    
    int main()
    {
      int i_a;
      
      for (;;){ //(*2)
        cout << "I want 0 = ";
        cin >> i_a;
        if (!i_a) break;
      }
      
      return 0;
    }
   └───────────────────────────────────┘
   ┌───────────────────────────────────┐
    [出力結果]
     I want 0 = 1
     I want 0 = 2
     I want 0 = 3
     I want 0 = 0
   └───────────────────────────────────┘


 goto文
 
  ・C++でもgoto文は使用できます。構造化プログラミングではコードのスパゲッティ化
   を避けるためにgotoの使用を避ける傾向にありますが、特定の状況(*3)においては
   便利でもあるため、制御文として残っています。
  
  ・goto文はラベル(label)へジャンプします。ラベルは後ろにコロン(:)を付けた識別
   子です。
   
   [List7.goto文の例]
   ┌───────────────────────────────────┐
    #include <iostream>
    using namespace std;
    
    int main()
    {
      int i_a;
      
      for (;;){ //(*2)
        cout << "I want 0 = ";
        cin >> i_a;
        if (!i_a) goto loop;
      }
      
      loop: //ラベル
      
      return 0;
    }
   └───────────────────────────────────┘
   ┌───────────────────────────────────┐
    [出力結果]
     I want 0 = 1
     I want 0 = 2
     I want 0 = 3
     I want 0 = 0
   └───────────────────────────────────┘


(*1)文法上はそうですが、各ステートメントの変更追加時にバグを作り込んだり、ブロッ
  ク内変数のスコープが曖昧になるので、常にブロック化することをお勧めします。

(*2)無限ループの表現は、while(1)ではなく、for(;;)が普通と書いてあるのですが、私は
  前者しか見たことがありません。

(*3)エラー処理や深いネストから抜ける場合等です。又は実行速度が何よりも優先される
  場合等も有効です。

[Revision Table]
 |Revision |Date    |Comments
 |----------|-----------|-----------------------------------------------------
 |1.00   |2002-08-15 |初版
[end]
Copyright(C) 2002 Altmo