C言語を学び始めると、プログラムに繰り返し処理を行わせる「ループ文」の重要性に気づくはずです。
その中でも do while文 は、他のループ文とは異なるユニークな特徴を持っています。
多くの初心者が最初に学習する while 文や for 文と何が違うのか、どのような場面で活用すべきなのかを理解することは、効率的でバグの少ないコードを書くための第一歩となります。
本記事では、do while文の基本構造から実践的な使い方、注意点までを詳しく解説します。
C言語におけるdo while文の基本概念
C言語には、特定の条件が満たされている間、処理を繰り返すための制御構文がいくつか用意されています。
その一つである do while文 は、「条件に関わらず、必ず一度は処理を実行する」 という性質を持っています。
一般的なプログラミングの流れでは、条件を確認してから処理を行うのが定石ですが、現実のプログラムでは「まず動かしてみて、その結果を見てから継続するか決める」というロジックが必要になる場面が多々あります。
do while文はこのニーズを直感的に記述するための構文です。
do while文の基本構文
do while文の書き方は非常にシンプルです。
以下の構造で記述されます。
do {
// 繰り返したい処理
} while (条件式);
この構文で最も重要なのは、最後に ; (セミコロン) が必要であるという点です。
これは、if 文や通常の while 文にはない特徴であり、初心者が最も間違いやすいポイントの一つです。
処理の流れ
do while文が実行されるとき、コンピュータは以下のステップを踏みます。
doブロック内の処理を無条件に実行する。whileの後ろにあるカッコ内の 条件式 を評価する。- 条件式が「真」(0以外) であれば、再び
doブロックの先頭に戻る。 - 条件式が「偽」(0) であれば、ループを終了して次の命令へ進む。
このように、処理が先に行われ、判定が後に行われることから、do while文は 後判定ループ と呼ばれます。
do while文とwhile文の決定的な違い
C言語には do while文に似た while 文が存在します。
これら二つの最大の違いは、「最初の1回目が実行されるかどうか」 にあります。
while文(前判定)の特徴
while 文は、処理に入る前に条件をチェックします。
そのため、もし最初から条件が偽であった場合、中の処理は 一度も実行されません。
int i = 10;
while (i < 5) {
printf("この処理は実行されません\n");
i++;
}
上記の例では、変数 i が10であり、条件 i < 5 を満たさないため、画面には何も表示されません。
do while文(後判定)の特徴
一方で、do while文は処理を行ってから条件をチェックします。
たとえ最初から条件が偽であっても、必ず1回は処理が実行されます。
int i = 10;
do {
printf("この処理は必ず1回は実行されます\n");
i++;
} while (i < 5);
この場合、条件 i < 5 は最初から偽ですが、一度 printf が実行された後に判定が行われるため、1行だけメッセージが表示されます。
比較表:while vs do while
以下の表は、両者の主な違いをまとめたものです。
| 特徴 | while文 | do while文 |
|---|---|---|
| 判定のタイミング | 処理の前(前判定) | 処理の後(後判定) |
| 最低実行回数 | 0回 | 1回 |
| セミコロンの有無 | 文末には不要(ブロック終了時) | while(...); のように必要 |
| 主な用途 | 条件によって実行自体をスキップしたい時 | 少なくとも一度は動かす必要がある時 |
do while文の具体的な活用シーン
理屈では理解できても、「1回だけ必ず実行される」という性質がどのような場面で役立つのかイメージしにくいかもしれません。
ここでは、実務や学習でよく遭遇する具体的なユースケースを紹介します。
1. ユーザーからの入力チェック(バリデーション)
do while文の最も代表的な使い道は、ユーザーに正しい値を入力させるまで繰り返す という処理です。
例えば、1から100までの数字を入力させたい場合、まずは入力を受け取らなければ「正しいかどうか」を判定できません。
#include <stdio.h>
int main() {
int num;
do {
printf("1から100までの数字を入力してください: ");
scanf("%d", &num);
} while (num < 1 || num > 100);
printf("入力された値は %d です。\n", num);
return 0;
}
このプログラムでは、まず scanf で入力を受け取り、その値が範囲外(1未満または100より大きい)であれば、再び do ブロックに戻って入力を促します。
これを while 文で書こうとすると、ループの外で一度入力を受け取る処理を書く必要があり、コードが重複してしまいます。
2. メニュー画面の表示
コンソールアプリケーションなどで、メニューを表示してユーザーに選択を求める処理にも適しています。
#include <stdio.h>
int main() {
int choice;
do {
printf("\n--- メニュー ---\n");
printf("1. データの表示\n");
printf("2. データの追加\n");
printf("0. 終了\n");
printf("選択してください: ");
scanf("%d", &choice);
switch (choice) {
case 1: printf("表示処理を実行します。\n"); break;
case 2: printf("追加処理を実行します。\n"); break;
case 0: printf("プログラムを終了します。\n"); break;
default: printf("無効な選択です。\n");
}
} while (choice != 0);
return 0;
}
「メニューを表示する」というアクションは、プログラムが始まった時点で必ず一度は行われるべきものです。
その後、ユーザーが「終了」を選択するまで繰り返すという流れは、do while文の構造に完璧に合致しています。
3. do-while(0) によるマクロの安全な実装
これは中級者以上のテクニックですが、C言語のプリプロセッサマクロにおいて do { ... } while(0) という形が使われることがあります。
#define SAFE_FREE(p) do { free(p); p = NULL; } while(0)
一見すると「1回実行してすぐ終わるなら意味がないのでは?」と思われますが、これはマクロを if 文の中で使った際に、セミコロンの有無による構文エラーや予期せぬ動作を防ぐための標準的な手法です。
do while文を使用する際の注意点
do while文は強力ですが、いくつか注意しなければならないポイントがあります。
これらを怠ると、バグの温床になったり、可読性が低下したりします。
セミコロンの付け忘れ
何度も強調しますが、while (条件式); の最後のセミコロンは必須です。
// 誤り
do {
// 処理
} while (i < 5) // ここにセミコロンがないとコンパイルエラー
// 正解
do {
// 処理
} while (i < 5);
コンパイラはこのセミコロンを見て「ここで do while文が終わる」と判断します。
忘れると、次の行のコードと繋がっていると解釈され、意味不明なエラーメッセージに悩まされることになります。
無限ループの発生
他のループ文と同様、条件式が常に真(0以外)になると 無限ループ に陥ります。
int i = 0;
do {
printf("%d\n", i);
// iを更新する処理(i++など)を忘れると無限ループになる
} while (i < 5);
ループ内で条件式に影響を与える変数の値が適切に更新されているか、必ず確認しましょう。
意図的に無限ループを作る場合は while(1) が一般的ですが、do while文で作成することも可能です。
変数のスコープ(有効範囲)
do while文の中で宣言した変数は、while の条件式の中では使用できません。
do {
int x = 10;
// 処理
} while (x > 0); // コンパイルエラー:xはこの範囲で未定義
条件式で使用する変数は、必ず do ブロックよりも前(外側)で宣言しておく必要があります。
これは、C言語のスコープ規則による制限です。
break文とcontinue文の挙動
do while文の中でも、ループを制御するための break と continue を使用できます。
break文による強制終了
break が実行されると、条件判定を待たずに即座にループを抜けます。
int i = 0;
do {
if (i == 3) break;
printf("%d ", i);
i++;
} while (i < 10);
// 出力結果: 0 1 2
特定の異常事態が発生した際や、ユーザーが特定の操作をした際にループを打ち切りたい場合に便利です。
continue文による処理のスキップ
continue が実行されると、それ以降のブロック内の処理をスキップし、直接条件判定(whileの部分)へジャンプ します。
int i = 0;
do {
i++;
if (i % 2 == 0) continue; // 偶数の時は printf をスキップ
printf("%d ", i);
} while (i < 5);
// 出力結果: 1 3 5
ここで注意したいのは、while 文と違い、continue した後に向かう先が「条件判定」であることです。
もし変数の更新処理(i++など)を continue よりも後ろに書いてしまうと、更新が行われず無限ループになるリスクがあります。
実践的なサンプル:数あてゲーム
これまでの知識を総動員して、do while文を活用した簡単な数あてゲームのプログラムを見てみましょう。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
int answer, guess, attempts = 0;
// 乱数の種を初期化して、1〜100の正解を作る
srand(time(NULL));
answer = rand() % 100 + 1;
printf("1から100までの数字を当ててみてください!\n");
do {
printf("予想を入力: ");
if (scanf("%d", &guess) != 1) {
printf("数字を入力してください。\n");
while(getchar() != '\n'); // 入力バッファのクリア
continue;
}
attempts++;
if (guess > answer) {
printf("もっと小さいです。\n");
} else if (guess < answer) {
printf("もっと大きいです。\n");
}
} while (guess != answer);
printf("おめでとうございます! %d 回目で正解しました。\n", attempts);
return 0;
}
このプログラムでは、以下の理由から do while文が最適です。
- ユーザーに少なくとも1回は回答を入力させる必要がある。
- 正解するまで何度でも入力を繰り返す。
- 入力が不正だった場合に
continueで再度入力を促す。
do while文とメモリ・パフォーマンスの関係
現代のコンピュータにおいて、for、while、do while の間に劇的なパフォーマンスの差はありません。
しかし、低レイヤーの視点で見ると興味深い違いがあります。
CPUが命令を実行する際、条件分岐(ジャンプ命令)はコストがかかる処理です。
do while文のような後判定ループは、多くの場合、アセンブリ言語に変換された際に「条件が真なら先頭に戻る」という単純なジャンプ命令1つで構成されやすいため、非常に効率的なループ構造といえます。
ただし、現代のコンパイラ(GCCやClangなど)は極めて優秀です。
コードの意図を読み取り、最適なマシンコードに変換してくれるため、プログラマが速度のために無理に do while文を選ぶ必要はありません。
それよりも、「コードの読みやすさ(可読性)」 を優先して、論理的に最も自然な構文を選ぶことが重要です。
他のループ文との使い分けの指針
どのループ文を使うべきか迷ったときは、以下のガイドラインを参考にしてください。
for文を使うべき時
- 繰り返す回数が最初から決まっている時(例:10回繰り返す)。
- 配列の要素を順番に処理する時。
- カウンタ変数の初期化、更新、判定を1行にまとめたい時。
while文を使うべき時
- 繰り返す回数が決まっていない時。
- 条件によっては、一度も実行したくない 時。
- ループの開始前に厳しいチェックが必要な時。
do while文を使うべき時
- 最低でも1回は実行 する必要がある時。
- 処理を実行した結果に基づいて、次を繰り返すか判断したい時。
- ユーザー入力のバリデーションやメニュー選択。
よくある質問(FAQ)
- do while文を全く使わなくてもプログラムは書けますか?
はい、理論上は可能です。
すべての do while文は、while 文とフラグ変数、あるいはループ前の重複コードで書き換えることができます。
しかし、do while文を使ったほうがコードが短くなり、意図が明確に伝わる場面が多いです。
- do whileの「do」のあとに中カッコ {} は必須ですか?
実行する文が1行だけであれば省略可能ですが、常に中カッコを付けることを強く推奨します。
C言語では、将来的に処理を追加した際のバグを防ぐため、1行であってもブロックで囲むのがプロの現場での一般的な習慣です。
- 条件式に 1 を入れたらどうなりますか?
do { … } while(1); と書くと、無限ループになります。
この場合、ブロック内のどこかで break や return を呼び出さない限り、プログラムは止まりません。
まとめ
C言語の do while文 は、他のループ文にはない「後判定」というユニークな仕組みを持っています。
- 必ず1回は実行される という特性を活かし、ユーザー入力やメニュー処理に利用する。
while (条件);の末尾にある セミコロンを忘れない。- 条件式で使用する変数は、ループの外で宣言する。
while文との違いを明確に理解し、状況に応じて最適なループを選択する。
これらのポイントを押さえておくことで、あなたのC言語のプログラミングスキルは一段階向上するはずです。
構文をただ暗記するのではなく、実際のプログラムの中で「ここなら do while文の方がスッキリ書けるな」という感覚を養っていきましょう。
より詳しい情報は、ISO/IEC 9899(C言語の標準規格)や、信頼できるプログラミングリソースを参考にしてください。
C言語の基礎を固めることは、C++やJava、Pythonといった他の言語を学ぶ際にも大きな財産となります。






