C言語編 第14章 同じ処理を繰り返す(while文)

先頭へ戻る

この章の概要

この章の概要です。

反復構造

第11章第12章第13章では、if文や switch文を使った、分岐構造を取り上げました。この章からは、反復構造を取り上げます。反復構造は、同じ内容の処理を何度も繰り返す構造で、ループ構造とも呼ばれます。

順次構造、分岐構造、反復構造を併せて、基本制御構造と呼ばれることがあります。 順次構造、分岐構造、反復構造の組み合わせでプログラムは表現可能であると言われています。

この考え方は、構造化プログラミングと呼ばれるもの(の一部)です。構造化プログラミング自体は、1960年代に提唱された非常に古いものですが、今でも、プログラミングの基本思想であり続けています。とりあえず、現状でそこまで深く考える必要はないでしょう。

C言語には、反復構造を表現するために幾つかの方法が用意されています。 この章では、一番単純な while文を取り上げます。

while文

まず、「標準入力から受け取った文字を、改行しながら10回出力する」ことを考えてみます。 反復構造の使い方を知らない現状では、次のように書くしかありません。

#include <stdio.h>

int main(void)
{
    char c;
    char str[20];

    puts( "1文字入力して下さい。" );
    fgets( str, sizeof(str), stdin );
    sscanf( str, "%c", &c );

    /* 10回出力する */
    printf( "%c\n", c );
    printf( "%c\n", c );
    printf( "%c\n", c );
    printf( "%c\n", c );
    printf( "%c\n", c );
    printf( "%c\n", c );
    printf( "%c\n", c );
    printf( "%c\n", c );
    printf( "%c\n", c );
    printf( "%c\n", c );

    return 0;
}

実行結果:

1文字入力して下さい。
y
y
y
y
y
y
y
y
y
y
y

こんなの面倒ですよね。 「そうでもない。別にコピー&ペーストしていけば 10個くらい・・・」という人もいるかも知れませんが、10回とは限りません。 10000回かも知れないし、「標準入力から受け取った回数分だけ出力する」かも知れません。 前者は(無駄な)努力をすれば可能ですが、後者は不可能です。 完成したプログラムを実行して、入力を行うまで、必要な回数は分からないのですから、 プログラムを書く段階ではどうしようもありません。

そこで、反復構造の出番です。 先ほどのプログラムは、while文を利用して次のように書き変えられます。

#include <stdio.h>

int main(void)
{
    char c;
    char str[20];
    int count;

    puts( "1文字入力して下さい。" );
    fgets( str, sizeof(str), stdin );
    sscanf( str, "%c", &c );

    /* 10回出力する */
    count = 0;
    while( count < 10 ){
        printf( "%c\n", c );
        count = count + 1;
    }

    return 0;
}

実行結果:

1文字入力して下さい。
y
y
y
y
y
y
y
y
y
y
y

while文の構造は、次のようになっています。

while( 条件式 ){
    ループさせる処理
}

if文のときと同じで、処理が1文だけであれば、 { } は省略することができますが、省略しないことを勧めます。

「条件式」の部分には、「処理を繰り返すのはどんなときか」を記述します。 条件式が偽の場合には、while文全体を終了させて、その後の処理へ進みます。 実行される処理の順序を整理すると、次のようになります。

  1. 「条件式」を調べる。「真」なら2へ。「偽」なら4へ。
  2. 「ループさせる処理」を実行する。3へ。
  3. 「ループさせる処理」が全て終了したら1へ戻る。
  4. while文を終了させて、次の処理へ進む。

したがって、1~3の部分がループしていることになります。 もし、初めて1に来た時点で、条件式が偽になっている場合は、ループ内の処理は1度も実行されません


では、先程のサンプルプログラムの詳細を確認しておきましょう。 このサンプルプログラムでは、「10回繰り返す」というように、ループさせる回数が定まっています。 この「回数」をうまく表現しなければなりません。

ループの回数を表現するには、それ専用の変数を1つ用意しておき、ここに「今のところ、何回ループしたか」を保存しておくのが簡単です。 今回のサンプルプログラムでは、変数count を用意しています。
while文に差し掛かる直前で、count の値を 0 にしておき(つまり、今のところ 0回ループした)、 while文の内部の最後のところで count の値を 1 増やしています。

while文の条件式には、「目的の回数に満たない」という意味合いの式を書けば、目的の回数だけループさせることができます。慣れるまで反対の意味の条件式を書いてしまいがちですが、「処理を繰り返すのはどんなときか」を書くということを意識して下さい。今回は、「処理を繰り返すのは、count の値が 10未満のとき」ですから、「count < 10」とします。

ところで、「10回繰り返す」ことが目的ならば、「count != 10」ではダメなのかという疑問も生まれるかも知れません。それでも正しく動作しますし、意味的にも間違っていません。しかし、一般的には「count != 10」よりも「count < 10」の方が好まれます。
その理由は、「何かの拍子に count の値が 10 を超えて、すり抜けてしまうかも知れない」という不安への対処のためです。count の値が必ず1ずつ増加しているなら、そんなことはあり得ないのですが、3ずつ増加させるように、プログラムの仕様を変更しなければならなくなったとしたらどうでしょう。count の取り得る値は「0、3、6、9、12…」と続きますから、決して 10 にはなりません。そうすると、「count != 10」という条件式はすり抜けて、いつまでも条件式は偽になりません。「count < 10」という条件式ならば、いつかは偽になるでしょうから、ループを抜け出すことができます。


練習問題

問題① 標準入力から入力された整数分だけ、'*' を出力するプログラムを作成して下さい。

問題② 標準入力から5の倍数の整数を入力させるプログラムを作成して下さい。 5の倍数でない値が入力された場合、何度でも再入力を促すようにして下さい。

問題③ 本文中のサンプルプログラム(標準入力から受け取った文字を 10回出力する)で、 while文の部分を、「今のところ何回ループしたか」という観点ではなく、 「あと何回ループさせるか」という観点で書き換えて下さい。


解答ページはこちら

参考リンク



更新履歴

'2018/2/7 全面的に文章を見直し、修正を行った。

'2009/3/27 新規作成。



前の章へ(第13章 複数の条件で分岐させる)

次の章へ(第15章 同じ処理を繰り返す(for文))

C言語編のトップページへ

Programming Place Plus のトップページへ


このエントリーをはてなブックマークに追加
rss1.0 取得ボタン RSS