C言語のきほん|do~while文の基本

最低1回は必ず動く。入力ループの強い味方、do~while文をスッと使えるようになろう。

do~while文は「まずやってみて、あとで続けるか決める」ループ

while文やfor文は、ループに入る前に条件をチェックする“前判定”でした。
それに対して do~while文 は、“後判定”です。

  • 先に処理を1回実行する
  • そのあとで続けるかどうかを判定する

なので、条件が最初から偽でも、最低1回は必ず処理が実行されるのが最大の特徴です。
「入力を必ず1回は受け付けたい」ときに、すごく自然に書けます。

do~while文の基本構文

do~while文はこの形です。最後にセミコロンが必要なのがポイントです。

do {
    文;
} while (継続条件式);

要素の意味を表で整理

要素意味覚えておくポイント
do { ... }まず1回実行する処理ここは必ず1回通る
while (継続条件式)続けるかどうかの判定真なら繰り返し、偽なら終了
末尾の ;構文の一部付け忘れるとコンパイルエラー

do~while文の流れ

ここがwhileと真逆のポイントです。

while文との違い(前判定と後判定)

条件チェックのタイミングが違う

ループ条件チェック条件が最初から偽だったら?
while実行前にチェック1回も実行されない
do~while実行後にチェックそれでも1回は実行される

使い分けのコツ

  • do~while:1回は必ずやりたい(入力受付、メニュー表示など)
  • while:条件を満たさないなら一切やりたくない(0件処理を許す場面)

サンプルプログラム

例:パスコードを当てるまで聞き続ける(必ず1回は入力させたい)

  • 正しいパスコードを 2468 とする
  • 正解するまで入力を繰り返す
  • 最初の1回は必ず聞く(ここがdo~while向き)

ファイル名:9_6_1.c

// do~whileで正しいパスコードが入力されるまで繰り返すプログラム
#include <stdio.h>

int main(void)
{
    int code;
    const int correct = 2468;

    do {
        printf("パスコードを入力してください(正解すると終了)> ");
        scanf("%d", &code);

        if (code != correct) {
            printf("違います。もう一度どうぞ。\n");
        }
    } while (code != correct);

    printf("正解です。ロックを解除します。\n");

    return 0;
}

この例がdo~whileに向いている理由

最初に入力を必ず1回させたいからです。
whileにすると「最初の条件判定のために入力を外で1回やる」形になりがちで、コードが少し回りくどくなります。

do~while文をwhile文で書くとどうなる?(比較の感覚をつかむ)

do~whileで書いた「入力→判定→繰り返し」は、whileでも書けます。
でもwhileだと、よくこうなります。

  • 最初の入力(初回入力)をループの前でやる
  • その後に while を回す

つまり、do~whileは「入力ループの型」が自然に書ける、というイメージです。

実践問題:正解するまで計算を出し続ける

次の計算の答えを、正しく入力するまで繰り返し質問してください。

  • 1280 - 345 の答えを入力させる
  • 正解したら 正しい結果を入力しました。 と表示して終了

実行イメージ

1280 - 345 の答えは?> 900
1280 - 345 の答えは?> 936
1280 - 345 の答えは?> 935
正しい結果を入力しました。

解答例

ファイル名:9_6_2.c

// 正しい答えを入力するまで計算問題を出し続けるプログラム
#include <stdio.h>

int main(void)
{
    int ans;
    const int a = 1280;
    const int b = 345;
    const int correct = a - b;

    do {
        printf("%d - %d の答えは?> ", a, b);
        scanf("%d", &ans);
    } while (ans != correct);

    printf("正しい結果を入力しました。\n");

    return 0;
}

解説

  • doの中で必ず1回は質問する
  • 正解するまで ans != correct が真なので繰り返す
  • 正解した瞬間に条件が偽になって終了

実践問題:複数回BMIを計算し、yなら続ける

元の問題はBMIを計算し、yなら続ける、nなら終了でしたね。
ここもメッセージや入力文を少し変えつつ、要点はそのままにします。

身長と体重からBMIを計算して表示し、続けるかどうかを y/n で判断してください。

  • 身長はcmで入力し、mに変換する
  • BMI = 体重(kg) ÷ (身長(m) × 身長(m))
  • 続行確認で y なら続ける、それ以外は終了
  • doubleをscanfで読むときは %lf を使う

実行イメージ

身長を入力してください(cm)> 170.0
体重を入力してください(kg)> 60.0
BMIは20.76です。
続けますか(y/n)> y
身長を入力してください(cm)> 160.0
体重を入力してください(kg)> 55.0
BMIは21.48です。
続けますか(y/n)> n
プログラムを終了します。

解答例

ファイル名:9_6_3.c

// do~whileでBMI計算を繰り返すプログラム
#include <stdio.h>

int main(void)
{
    double height_cm, weight;
    char cont;

    do {
        printf("身長を入力してください(cm)> ");
        scanf("%lf", &height_cm);

        printf("体重を入力してください(kg)> ");
        scanf("%lf", &weight);

        double height_m = height_cm / 100.0;
        double bmi = weight / (height_m * height_m);

        printf("BMIは%.2fです。\n", bmi);

        printf("続けますか(y/n)> ");
        scanf(" %c", &cont);  // 先頭のスペースで改行を読み飛ばす
    } while (cont == 'y');

    printf("プログラムを終了します。\n");

    return 0;
}

解説(ここがつまずきポイント)

  • scanfで文字を読むとき、直前の改行を拾ってしまうことがある
    だから " %c" のように先頭にスペースを入れて、空白を読み飛ばします。
  • do~whileなので、最初のBMI計算は必ず1回行われます。
  • 継続条件は cont == 'y'。y以外なら終了という仕様にピッタリです。

実践問題:判定+適正体重との差

チャレンジ問題:ch9_3_a.c(オリジナル)

BMI計算を繰り返し、次を表示してください。

  • 判定(低体重、普通体重、肥満1度…)
  • BMI(小数第2位まで)
  • 適正体重との差(kg)を + や - 付きで表示
  • 適正体重(kg) = 身長(m) × 身長(m) × 22
  • 続行は y のときだけ続ける

判定表

BMI判定
18.5未満低体重(痩せ型)
18.5以上25未満普通体重
25以上30未満肥満(1度)
30以上35未満肥満(2度)
35以上40未満肥満(3度)
40以上肥満(4度)

解答例

// do~whileでBMIを繰り返し計算し、判定と適正体重との差も表示するプログラム
#include <stdio.h>

int main(void)
{
    double height_cm, weight;
    char cont;

    do {
        printf("身長を入力してください(cm)> ");
        scanf("%lf", &height_cm);

        printf("体重を入力してください(kg)> ");
        scanf("%lf", &weight);

        double height_m = height_cm / 100.0;
        double bmi = weight / (height_m * height_m);
        double standard = height_m * height_m * 22.0;
        double diff = weight - standard;

        const char *judge;
        if (bmi < 18.5) {
            judge = "低体重(痩せ型)";
        } else if (bmi < 25.0) {
            judge = "普通体重";
        } else if (bmi < 30.0) {
            judge = "肥満(1度)";
        } else if (bmi < 35.0) {
            judge = "肥満(2度)";
        } else if (bmi < 40.0) {
            judge = "肥満(3度)";
        } else {
            judge = "肥満(4度)";
        }

        // %+ は符号を必ず付ける(+3.20 や -3.20 のように表示)
        printf("判定:%s  BMI:%.2f  適正体重との差:%+.2f kg\n", judge, bmi, diff);

        printf("続けますか(y/n)> ");
        scanf(" %c", &cont);
    } while (cont == 'y');

    printf("プログラムを終了します。\n");

    return 0;
}

解説(この問題の“おいしい”ポイント)

  • do~whileは「最低1回実行」が保証されるので、計算→続行確認の流れが自然
  • 判定はif~else if~elseの範囲判定が向いている
  • 適正体重との差は diff = 体重 - 適正体重
  • printfの %+ を使うと、プラスでも符号が付いて見やすい(例:+4.90 kg)

必要なら、この次の流れとして「do~whileが特にハマるメニュー処理(1回は必ずメニューを表示したい)」のパターンも、同じトーンで続編として作れます。