アンケートを取ります。「まず1回は必ず質問する。答えが変だったら、もう一度聞く」。while だと「聞く前に条件を確かめる」ことになって、少し不自然です。こういうときはdo-while文が素直に書けます。
do {
処理
} while (継続条件); // ← セミコロンを忘れずにwhileとの違いは1点だけ。条件を確かめるのが後なので、条件が最初から偽でも本体は必ず1回は実行されます。「とりあえずやってみて、駄目ならもう一度」という形です。
入力チェックで使ってみましょう。
#include <stdio.h>
int main(void) {
int n;
do {
printf("1〜10の数を入力: ");
if (scanf("%d", &n) != 1) { // 数字以外が入力された
printf("数字を入れてください\n");
return 1;
}
} while (n < 1 || n > 10);
printf("%d を受け付けました\n", n);
return 0;
}「範囲外なら、もう一度聞く」がそのまま条件になっています。
注目してほしいのが scanf の戻り値をチェックしている点です。scanfは「読み取りに成功した項目の数」を返すので、%d が1つなら成功時は 1 が返ります。!= 1 なら数字ではなかった、と判定できます。ここで抜けずに聞き直そうとすると、読めなかった文字が入力に残ったままなので、同じ失敗を延々と繰り返す無限ループになります(第4トラックで見た scanf の罠です)。今はひとまず、戻り値を見て抜ける形にしておきます。
罠を2つ。
その1、末尾のセミコロン。 } while (条件); の ; を忘れるとコンパイルエラーになります。これは即座に怒られるので、まだ親切な部類です。
その2、条件の向き。 これが本命です。while に書くのは「続ける条件」であって、「やめる条件」ではありません。「1〜10なら受け付ける」と考えて while (n >= 1 && n <= 10); と書いてしまうと、意味が完全に裏返ります。
// 間違い: 正しい値を入れるほど聞き直される
do {
printf("1〜10の数を入力: ");
scanf("%d", &n);
} while (n >= 1 && n <= 10);5 を入れると「範囲内だから続ける」となって何度も聞かれ、99 を入れた瞬間に抜けてしまう。チェックの意味が消えています。書いたら「どういうときに、もう一度聞きたいのか」を日本語で言い直して、そのまま条件に翻訳してください。「範囲外なら、もう一度」→ n < 1 || n > 10 です。
まとめます。do-while は本体を必ず1回実行してから条件を見る。末尾にセミコロンが要る。条件は「続ける条件」——入力チェックなら「範囲外なら続ける」。