C言語の基本|while文を使いこなす

終わる回数が分からなくても大丈夫。条件を見ながら繰り返すwhile文で、実用的なプログラムへ一歩進もう。

プログラムの繰り返し処理では、あらかじめ何回処理するのか分かっている場合もあれば、実行してみるまで何回繰り返すのか分からない場合もあります。

たとえば、1から10まで順番に表示する処理であれば、繰り返す回数は最初から分かっています。このような処理はfor文で表現すると分かりやすくなります。

一方で、次のような処理はどうでしょうか。

  • 正しい値が入力されるまで入力を続ける
  • 終了を表す値が入力されるまで処理する
  • ある条件を満たしている間だけ処理する
  • 目標の値になるまで入力を繰り返す

このような処理では、何回繰り返せば終了するのかを最初に決めることができません。

そこで活躍するのがwhile文です。

while文は、条件式が真である間、同じ処理を繰り返します。入力によって条件が変化する処理との相性がよく、利用者の操作を受け付けるプログラムなどにも応用しやすい構文です。

ここでは、while文を単独で使うだけでなく、if文と組み合わせたり、入力によって繰り返し方を変えたりしながら、while文の使い方を詳しく見ていきます。

for文とwhile文を使い分ける

for文とwhile文は、どちらも繰り返し処理に使います。

大きな違いは、繰り返す回数をあらかじめ考えやすいかどうかです。

状況向いている構文使用例
繰り返す回数が決まっているfor文1から100まで表示する
要素数に合わせて処理するfor文配列の先頭から最後まで処理する
終了する回数が分からないwhile文特定の値が入力されるまで続ける
条件が成立している間だけ続けるwhile文入力値が範囲内である間処理する

もちろん、for文で書ける処理をwhile文で書くこともできますし、その逆もできます。

大切なのは、どちらを使えば処理の意図を読み取りやすいかです。

回数を基準に考えるならfor文、条件を基準に考えるならwhile文、と考えておくと使い分けやすくなります。

図1:for文とwhile文の使い分け

この図から分かること

for文とwhile文の違いは、単純に書き方が違うだけではありません。

for文は、何回繰り返すのかが分かっている処理を整理しやすく、while文は、終了条件を満たすまで続けたい処理を整理しやすい構文です。

特に入力処理では、利用者が何回目に終了条件を入力するか分かりません。そのため、条件を確認しながら処理を続けるwhile文が自然な選択になります。

while文の基本的な動き

while文の基本形は次のようになります。

while (条件式) {
    繰り返す処理;
}

処理の流れはとてもシンプルです。

  1. whileの条件式を確認する
  2. 条件式が真ならブロック内を実行する
  3. ブロックの最後まで進んだら再び条件式を確認する
  4. 条件式が真なら再び処理する
  5. 条件式が偽になったらwhile文を終了する

重要なのは、while文では処理を実行する前に条件を判定する点です。

最初の条件判定ですでに偽だった場合、while文の中は一度も実行されません。

入力によって条件を変えるwhile文

入力処理とwhile文を組み合わせる場合、非常によく使われる形があります。

処理の流れは次のようになります。

  1. 最初の値を入力する
  2. 入力された値を条件式で判定する
  3. 条件を満たしていれば処理する
  4. 次の値を入力する
  5. 新しい値でもう一度条件を判定する

ここで特に大切なのが、while文の前に行う最初の入力です。

たとえば次のような変数があるとします。

int value;

valueには、宣言しただけでは有効な入力値が設定されていません。

その状態で次のように判定するのは適切ではありません。

while (value != -1) {

そこで、最初のwhile判定より前にscanfで値を入力しておきます。

scanf("%d", &value);

while (value != -1) {

これによって、最初の条件判定から入力済みの値を使うことができます。

終了を表す特別な値

入力を繰り返すプログラムでは、特定の値を終了の合図として利用することがあります。

たとえば、

  • -1が入力されたら終了する
  • 0が入力されたら終了する
  • 999が入力されたら終了する

といった方法です。

このように、通常のデータとは別に終了を知らせるために使う特別な値をセンチネルと呼ぶことがあります。

図2:入力と条件判定を繰り返すwhile文

この図から分かること

入力を使ったwhile文では、条件式だけを見るのではなく、条件に使っている変数がどこで変化するかを確認することが重要です。

最初に入力した値を条件判定に使用し、while文の中で次の入力を受け取ります。その結果、次回の条件判定では新しい値が使われます。

この繰り返しによって、終了値が入力されるまで処理を続けることができます。

入力された値を集計しながら繰り返す

それでは、終了値が入力されるまで数値を受け取り、その個数と合計を求めるプログラムを見てみましょう。

ここでは-1を終了の合図として使用します。

  • 整数を1つ入力する
  • -1以外なら合計に加える
  • 入力個数を1増やす
  • 次の整数を入力する
  • -1が入力されたら終了する
入力値の個数と合計を求めるプログラム

ファイル名:9_2_1.c

// -1が入力されるまで整数を受け取り、入力個数と合計を求めるプログラム
#include <stdio.h>

int main(void)
{
    int value;
    int total = 0;
    int count = 0;

    printf("整数を入力してください(-1で終了)> ");
    scanf("%d", &value);

    while (value != -1) {
        total += value;
        count++;

        printf("整数を入力してください(-1で終了)> ");
        scanf("%d", &value);
    }

    printf("入力した個数は%d個です。\n", count);
    printf("入力した値の合計は%dです。\n", total);

    return 0;
}
実行結果の例
整数を入力してください(-1で終了)> 8
整数を入力してください(-1で終了)> 4
整数を入力してください(-1で終了)> 6
整数を入力してください(-1で終了)> -1
入力した個数は3個です。
入力した値の合計は18です。

9_2_1.cの処理を詳しく見る

まず、入力値を保存するvalueと、合計を保存するtotal、個数を保存するcountを用意しています。

int value;
int total = 0;
int count = 0;

totalとcountは計算に使用するため、最初に0で初期化しています。

続いて、while文に入る前に最初の入力を受け取ります。

printf("整数を入力してください(-1で終了)> ");
scanf("%d", &value);

この入力によって、最初のwhile判定に必要なvalueが決まります。

while (value != -1) {

valueが-1ではない間だけ、while文の中を実行します。

入力された値はtotalに加算します。

total += value;

これは次の処理と同じ意味です。

total = total + value;

さらに、入力された値を1個として数えます。

count++;

処理の最後でもう一度入力します。

scanf("%d", &value);

ここが非常に重要です。

新しく入力された値によってvalueが変わるため、次回のwhile判定の結果も変化します。

最終的に-1が入力されると、

value != -1

が偽になり、while文を抜けます。

終了値として使っている-1はwhile文の中に入らないため、合計にも個数にも含まれません。

このプログラムを3つの部分に分けると、次のようになります。

部分役割
while文の前の入力最初の条件判定に使う値を用意する
while文の中集計処理と次の入力を行う
while文の後繰り返し終了後の結果を表示する

入力を使うwhile文では、この形を覚えておくとさまざまな処理に応用できます。

while文の中でif文を使う

while文では、同じ処理を繰り返すだけでなく、その途中で条件によって処理を分けることもできます。

そのときに利用するのがif文です。

基本的な形は次のようになります。

while (条件式) {
    if (別の条件式) {
        処理A;
    } else {
        処理B;
    }

    更新処理;
}

while文は繰り返す範囲を決め、if文はその1回ごとの処理内容を決める、と考えると分かりやすくなります。

たとえば、1から8までの整数を順番に調べながら、3の倍数かどうかによって表示内容を変えることができます。

3の倍数かどうかを判定しながら繰り返すプログラム

ファイル名:9_2_2.c

// while文で1から8まで繰り返し、3の倍数かどうかを判定するプログラム
#include <stdio.h>

int main(void)
{
    int i = 1;

    while (i <= 8) {
        if (i % 3 == 0) {
            printf("%dは3の倍数です。\n", i);
        } else {
            printf("%dは3の倍数ではありません。\n", i);
        }

        i++;
    }

    return 0;
}
実行結果の例
1は3の倍数ではありません。
2は3の倍数ではありません。
3は3の倍数です。
4は3の倍数ではありません。
5は3の倍数ではありません。
6は3の倍数です。
7は3の倍数ではありません。
8は3の倍数ではありません。

9_2_2.cの処理を詳しく見る

最初に、繰り返しに使用する変数iを1で初期化します。

int i = 1;

while文では、iが8以下の間だけ処理を続けます。

while (i <= 8) {

while文の中にはif文があります。

if (i % 3 == 0) {

%は余りを求める演算子です。

3で割った余りが0なら、その数は3の倍数です。

そのため、

i % 3 == 0

によって3の倍数かどうかを判定できます。

そして、while文の最後には次の処理があります。

i++;

これは非常に重要な処理です。

i++によって、

1
2
3
4
5
...

とiの値が変化していきます。

もしi++を書かなかった場合、iはいつまでも1のままです。

すると、

i <= 8

はずっと真のままとなり、while文が終了しません。

このように、while文を書くときは、条件式だけでなく、条件に使っている値が繰り返しの中で変化しているかも確認する必要があります。

while文とif文の役割を整理する

9_2_2.cでは、それぞれの構文に異なる役割があります。

構文・処理役割
while1から8まで繰り返す
if3の倍数かどうかを判定する
else条件を満たさない場合を処理する
i++次の値へ進める

つまり、

while文で繰り返し、if文でその都度判断する

という構造になっています。

この組み合わせは、入力されたデータを1件ずつ判定するときなどにも使いやすい形です。

if文の中でwhile文を使う

これまではwhile文の中にif文を入れました。

今度は反対に、if文の中でwhile文を実行する形を見てみましょう。

この形では、

  1. if文でどの処理を行うか決める
  2. 選ばれた処理の中でwhile文を実行する

という流れになります。

利用者が選択したモードによって、繰り返し方を変更したい場合に便利です。

選択したモードによって数値の表示順を変えるプログラム

ファイル名:9_2_3.c

// 選択されたモードに応じて、while文の進み方を変えるプログラム
#include <stdio.h>

int main(void)
{
    int mode;

    printf("表示モードを選んでください(1:昇順 2:降順)> ");
    scanf("%d", &mode);

    if (mode == 1) {
        int i = 2;

        while (i <= 8) {
            printf("数値:%d\n", i);
            i += 2;
        }
    } else {
        int i = 8;

        while (i >= 2) {
            printf("数値:%d\n", i);
            i -= 2;
        }
    }

    return 0;
}
実行結果の例:1を入力した場合
表示モードを選んでください(1:昇順 2:降順)> 1
数値:2
数値:4
数値:6
数値:8
実行結果の例:2を入力した場合
表示モードを選んでください(1:昇順 2:降順)> 2
数値:8
数値:6
数値:4
数値:2

9_2_3.cの処理を詳しく見る

最初にmodeへ利用者の選択を入力します。

scanf("%d", &mode);

その後、if文によって処理を分けています。

if (mode == 1) {

modeが1の場合は、iを2から始めます。

int i = 2;

そして、

while (i <= 8) {

によって8以下の間だけ処理します。

1回処理するたびに、

i += 2;

としているため、

2
4
6
8

と増えていきます。

一方、modeが1ではなかった場合は、iを8から始めます。

int i = 8;

こちらでは、

while (i >= 2) {

として2以上の間だけ繰り返します。

さらに、

i -= 2;

によって、

8
6
4
2

と減少していきます。

このプログラムでは、if文とwhile文の役割がはっきり分かれています。

  • if文は繰り返し方を選ぶ
  • while文は選ばれた方針に従って処理を繰り返す

メニューで動作モードを選択してから処理を開始するようなプログラムでも、この考え方を利用できます。

while文では更新処理を忘れない

while文で特に注意したいのが、条件に関係する変数の更新です。

たとえば、次のwhile文を考えてみましょう。

int i = 1;

while (i <= 5) {
    printf("%d\n", i);
}

iは最初に1になっていますが、while文の中で値を変更していません。

そのため条件式は何度判定しても、

1 <= 5

となり、真のままです。

結果として処理が終了しなくなります。

そこで、次のように更新処理を入れます。

int i = 1;

while (i <= 5) {
    printf("%d\n", i);
    i++;
}

これならiが、

1 → 2 → 3 → 4 → 5 → 6

と変化します。

iが6になると、

i <= 5

が偽になり、while文は終了します。

入力を条件にしている場合も同じです。

scanf("%d", &value);

while (value != -1) {
    scanf("%d", &value);
}

scanfによってvalueが更新されるため、いつか-1が入力されれば条件式が偽になります。

while文を見るときは、

  • 何を条件にしているか
  • その値はどこで変化するか
  • 最終的に条件が偽になる可能性があるか

という3点を確認すると、無限ループを見つけやすくなります。

実践:目標の合計になるまで入力する

最後に、入力結果によって繰り返し回数が決まるプログラムを考えてみましょう。

2つの整数を入力し、その合計が12になるまで入力を繰り返します。

処理は次の流れです。

  1. 整数を2つ入力する
  2. 2つの整数を加算する
  3. 合計が12かどうか確認する
  4. 12でなければ再入力する
  5. 合計が12になったら終了する

何回目の入力で12になるかは、利用者が入力する値によって変わります。

そのため、繰り返し回数を最初から決めるよりも、合計が12ではない間繰り返すと考える方が自然です。

図3:目標の合計になるまで繰り返す処理

この図から分かること

この処理では、繰り返す回数ではなく、合計が12になったかどうかが終了の基準になっています。

入力するたびに合計が変化し、その新しい合計をwhile文の条件式で確認します。

このように、

入力 → 計算 → 判定 → 再入力

を繰り返しながら目標条件を満たす処理は、while文が得意とする代表的なパターンです。

2つの整数の合計が12になるまで入力を繰り返すプログラム

ファイル名:9_2_4.c

// 2つの整数の合計が12になるまで入力を繰り返すプログラム
#include <stdio.h>

int main(void)
{
    int a;
    int b;
    int sum;

    printf("整数を2つ入力してください > ");
    scanf("%d%d", &a, &b);

    sum = a + b;

    while (sum != 12) {
        printf("合計は%dです。まだ12ではありません。\n", sum);

        printf("整数を2つ入力してください > ");
        scanf("%d%d", &a, &b);

        sum = a + b;
    }

    printf("合計は12です。達成しました!\n");

    return 0;
}
実行結果の例
整数を2つ入力してください > 2 5
合計は7です。まだ12ではありません。
整数を2つ入力してください > 3 4
合計は7です。まだ12ではありません。
整数を2つ入力してください > 5 7
合計は12です。達成しました!

9_2_4.cの処理を詳しく見る

最初に2つの整数を保存するaとb、合計を保存するsumを宣言します。

int a;
int b;
int sum;

次に、最初の2つの整数を入力します。

printf("整数を2つ入力してください > ");
scanf("%d%d", &a, &b);

入力した値から最初の合計を求めます。

sum = a + b;

この計算は、while文に入る前に必要です。

続く条件式ではsumを使用するからです。

while (sum != 12) {

sumが12ではない間、while文の中を繰り返します。

たとえばaが2、bが5なら、

sum = 2 + 5

なのでsumは7です。

sum != 12

は真になるため、while文の中へ進みます。

現在の合計を表示した後、もう一度2つの整数を入力します。

printf("整数を2つ入力してください > ");
scanf("%d%d", &a, &b);

そして、新しく入力された値を使ってsumを更新します。

sum = a + b;

ここがこのwhile文の重要な更新処理です。

新しいsumでwhile文の条件式が再び判定されます。

たとえば5と7が入力された場合、

5 + 7 = 12

となります。

このとき、

sum != 12

は偽になるためwhile文を終了します。

while文を抜けたということは、このプログラムではsumが12になったということです。

そこで最後に、

printf("合計は12です。達成しました!\n");

を実行します。

この問題がwhile文に向いている理由

このプログラムでは、利用者がどのような数値を入力するかを事前に予測できません。

1回目で合計が12になる場合もあれば、2回、3回、それ以上入力しなければならない場合もあります。

つまり、重要なのは繰り返し回数ではありません。

重要なのは、

sum != 12

という条件です。

sumが12ではない間は続け、12になったら終了します。

このような処理を見るときは、

何回繰り返すのかではなく、何が起きたら終了するのか

を考えてみてください。

終了条件を基準に処理を組み立てると、while文を使うべき場面を判断しやすくなります。

while文を読むときの確認ポイント

while文を使ったプログラムでは、次の順番でコードを見ると処理を理解しやすくなります。

  1. while文の条件式を確認する
  2. 条件式に使われている変数の初期値を確認する
  3. while文の中で何を処理しているか確認する
  4. 条件に使われている値がどこで更新されるか確認する
  5. どのような状態になれば条件式が偽になるのか確認する

たとえば9_2_4.cなら、

while (sum != 12)

が条件式です。

sumの最初の値は、

sum = a + b;

で設定されています。

さらにwhile文の中でも、

sum = a + b;

によって更新されています。

そしてsumが12になれば、

sum != 12

が偽になって終了します。

このように、初期値 → 条件判定 → 処理 → 更新 → 再判定という流れを追いかけることが、while文を使いこなすための大切なポイントです。