【C言語】while と do while の違い

whileとdo whileの違いの解説ページアイキャッチ

このページでは、C言語における「whiledo while の違い」について解説していきます。

whiledo while も両方ともループを実現するためのものになりますが、動作に違いがあります。その違いに焦点を当てて解説を行なっていきます。

while:最初に継続するかどうかを判断する

whiledo while の決定的な違いは、ループを継続するかどうかを判断するタイミングです。

while の場合、ループを継続するかどうかの判断が「繰り返す処理 を実行する前」に毎回行われます。

while は下記のように 継続条件繰り返す処理 を記述することでループを実現し、継続条件 が成立している間、繰り返す処理 の実行が繰り返されることになります。逆に 継続条件 が不成立になった際には、ループを抜け出し、繰り返す処理 の実行が終了することになります。

whileループ
while (継続条件) {
    繰り返す処理
}

例えば下記では、i10 未満である間、printf("%d\n", i)i++ の処理が繰り返されることになります(なので、実行すれば 09 が出力される)。

10回ループを継続
int i = 0;

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

前述の通り、while では「繰り返す処理 を実行する前」にループを継続するかどうかの判断が行われます。もう少し分かりやすくいうと、while ではループに入る前にも 継続条件 が成立しているかどうかが判断されます。

そして、継続条件 が成立している場合はループに入り、継続条件 が成立していない場合はループに入らないよう制御されます。それ以降は、次の 繰り返す処理 を行う前のタイミングで再び 継続条件 が成立しているかどうかが判断され、その結果に応じてループを続ける or ループを終了するかの制御が行われます。

ですので、先程の例において、i の初期値を 10 にすると、ループに入る前に i < 10 が成立していないと判断されるためループに入りません。そのため、printf("%d\n", i)i++ の処理は1度も実行されないことになります。

ループが行われない
int i = 10;

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

また、ループに入る前にも 継続条件 が成立しているかどうかの判断が行われるため、継続条件 で変数を使用している場合、その変数には必ず何かしらの値を初期化 or 代入によって格納しておく必要があります。

もし、これを行わなければ、その変数に不定値が格納されたままで 継続条件 が成立しているかどうかの判断が行われますので、意図した通りにループが動作しないことになります。

例えば下記は、i0 になるまで scanfi に格納する整数の入力を受け付け、i の値を2乗した結果を printf で表示する while ループの例となります。

不定値を用いて判断が行われる例
int i;

while (i != 0) {
    scanf("%d", &i);
    printf("%d", i * i);
}

上記においては、ループに入る前に i != 0 が成立するかどうかの判断が行われますが、その前に i の初期化や代入が行われていないため、i には不定値が格納されていることになります。なので、i != 0 が成立するかどうかの判断は正しく行うことができません。

その不定値がたまたま 0 以外の値であれば、上手く動作するかもしれませんが、不定値が 0 であればループ内の処理は一度も行われないことになります。

このように、特に while ループの場合、ループに入る前に 継続条件 が成立するかどうかの判断が行われますので、継続条件 の中で使用している変数には「適切な値」を格納しておく必要があります。ループの中で変数に値を格納しているからといって変数を不定値のままにしておくと、上手くループを動作させることができないので注意してください。

do while:最後に継続するかどうかを判断する

while では「繰り返す処理 を実行する前」にループを継続するかどうかの判断が行われるのに対し、do while では「繰り返す処理 を実行した後」にループを継続するかどうかの判断が行われます。

do while は下記のように 継続条件繰り返す処理 を記述することでループを実現し、継続条件 が成立している間、繰り返す処理 の実行が繰り返されることになります。逆に 継続条件 が不成立になった際には、ループを抜け出し、繰り返す処理 の実行が終了することになります。

do whileループ
do {
    繰り返す処理
} while (継続条件);

while (継続条件) の後ろには ; が必要なので注意してください(私は結構つけ忘れる…)。 

例えば下記では、i10 未満である間、printf("%d\n", i)i++ の処理が繰り返されることになります(なので、実行すれば 09 が出力される)。

10回ループを継続
int i = 0;

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

この例だけ見ると、while と書き方は異なるものの、ほとんど同じように動作するように感じるかもしれません。

ただ、前述の通り、do while では「繰り返す処理 を実行した後」にループを継続するかどうかの判断が行われます。したがって、while とは異なり、ループに入る前には 継続条件 が成立しているかどうかの判断が行われません。

そのため、do while においては、必ず1度は 繰り返す処理 が実行されることになります。ここが while と動作が大きく異なる点になります。

ですので、先程の例において、i の初期値を 10 にしても、ループに入る前には 継続条件 の成立 or 不成立が判断されないため、必ず一度は printf("%d\n", i)i++ の処理が実行されることになります。

一度は繰り返す処理が実行される
int i = 10;

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

whiledo while とでは、ループを継続するかどうかの判断を行うタイミングが異なるため、while では 繰り返す処理 が一度も実行されないことがありますが、do while では 繰り返す処理 が必ず一度は実行されることになります。この点が whiledo while のどちらを使うかの判断材料となります。

また、while では、必ずループに入る前に 継続条件 で使用する変数に適切な値を格納しておく必要がありますが、do while ではループに入った後に 繰り返す処理 の中で 継続条件 で使用する変数に値を格納するのでも正常にループを動作させることができます(もちろん do while でも変数を初期化しておくに越したことはありません)。

スポンサーリンク

whiledo while の使い分け

最後に、whiledo while との使い分けについて解説しておきます。

正直いうと、私は do while はあまり利用したことはないです。大体 while でやりたいループは実現することができます。ただ、do while を使った方がソースコードがスッキリすることがあることは確かですし、やりたいループを実現しやすい場合もあります。

前述の通り、whiledo while のどちらを使うかの判断材料は下記になると思います。

  • while繰り返す処理 が一度も実行されないことがある
  • do while繰り返す処理 が必ず一度は実行される

このような違いがあるため、ループを組む際に 繰り返す処理 を必ず一度は実行させるようにしたい場合、do while を用いた方がソースコードがスッキリすることがあります。

すぐに思いつくのは、繰り返し scanfでユーザーからの入力受付を行う場合に一度は必ず入力を受け付けたい場合や、ファイルの最後まで繰り返しファイルの中身の読み込みを行う場合などですかね。

例えば、下記は簡単なクイズを出題する場合の do while の使用例となります。

必ず一度は処理を実行する例
int ans1, ans2, ans3;

do {
    printf("Q1: 1 + 2 = ");
    scanf("%d", &ans1);
} while (ans1 != (1 + 2));

do {
    printf("Q2: 1 * 2 = ");
    scanf("%d", &ans2);
} while (ans2 != (1 * 2));

do {
    printf("Q3: 1 %% 2 = ");
    scanf("%d", &ans3);
} while (ans3 != (1 % 2));

printf("CLEAR!!!\n");

各ループの中で printf で出題された計算クイズの答えの入力を scanf 関数で受け付け、入力された値が不正解の間はループを抜けないように制御を行なっています(入力された値が正解であれば、ループを抜けて次のクイズの出題に移る)。

このようなプログラムの場合、各クイズに対して必ず一度は printf 関数と scanf 関数を実行することになります。なので、ループ内の printf 関数と scanf 関数が必ず一度は実行されるよう、do while でループを作るようにしています。

同様の処理は while でも実現できますが、この場合は、while ループの外側で一度 printf 関数と scanf 関数を実行する必要がありますので、ちょっと do while の時に比べるとソースコードが冗長になってしまうかなぁという印象です。

whileで必ず一度は処理を実行する例1
int ans1, ans2, ans3;

printf("Q1: 1 + 2 = ");
scanf("%d", &ans1);
while (ans1 != (1 + 2)) {
    printf("Q1: 1 + 2 = ");
    scanf("%d", &ans1);
}

printf("Q2: 1 * 2 = ");
scanf("%d", &ans2);
while (ans2 != (1 * 2)) {
    printf("Q2: 1 * 2 = ");
    scanf("%d", &ans2);
}

printf("Q3: 1 %% 2 = ");
scanf("%d", &ans3);
while (ans3 != (1 % 2)) {
    printf("Q3: 1 %% 2 = ");
    scanf("%d", &ans3);
}

printf("CLEAR!!!\n");

また、while の場合でも、下記のように事前に ans1ans2ans3 に正解とは異なる値を格納しておけば、ループの外側での printf 関数と scanf 関数の実行も無くすことはできます。

ソースコードは短くなりますが、しっかりコメントを書いておかないと処理が理解しにくいかなぁと思いますし、この書き方をするくらいなら do while を使えば良いのに…、と私なら感じてしまいますね…。

whileで必ず一度は処理を実行する例2
int ans1 = 0, ans2 = 0, ans3 = 0;

while (ans1 != (1 + 2)) {
    printf("Q1: 1 + 2 = ");
    scanf("%d", &ans1);
}

while (ans2 != (1 * 2)) {
    printf("Q2: 1 * 2 = ");
    scanf("%d", &ans2);
}

while (ans3 != (1 % 2)) {
    printf("Q3: 1 %% 2 = ");
    scanf("%d", &ans3);
}

printf("CLEAR!!!\n");

こんな感じで、ループの中の 繰り返す処理 を一度は必ず行いたい場合、do while を利用することでスッキリしたソースコードに仕立てることができる場合があります。

基本は while の方が使用する機会は多いと思いますが、繰り返す処理 を一度は必ず行いたいという場合は、do while を利用することも検討してみると良いと思います。

まとめ

このページでは、C言語における「whiledo while の違い」について解説しました。

whiledo while では、指定した継続条件の成立 or 不成立の判断が行われるタイミングに違いがあります。

  • while繰り返す処理 実行前
  • do while繰り返す処理 実行後

この違いにより、while では 繰り返す処理 が一度も実行されないことがありますが、do while では 繰り返す処理 が必ず一度は実行されることになります。

そのため、繰り返す処理 を必ず一度は実行するようにしたい際には、do while を使用することでソースコードがスッキリする場合があります。

ただ、使用する機会 while の方が多いと思いますので、まずは while でループを実現し、その後、そのループが 「繰り返す処理 を必ず一度は実行する」ものである場合に、do while を利用することを検討してみる流れで実装していくのが良いかなぁと思います。

また、今回は whiledo while の違いについて解説しましたが、forwhile の使い分けについても下記ページで解説していますので、興味があれば是非読んでみて下さい!

forとwhileの使い分けの解説ページアイキャッチfor と while の使い分け

オススメの参考書

C言語学習中だけど分からないことが多くて挫折しそう...という方には、下記の「スッキリわかるC言語入門」がオススメです!

まず学習を進める上で、参考書は2冊持っておくことをオススメします。この理由は下記の2つです。

  • 参考書によって、解説の仕方は異なる
  • 読み手によって、理解しやすい解説の仕方は異なる

ある人の説明聞いても理解できなかったけど、他の人からちょっと違った観点での説明を聞いて「あー、そういうことね!」って簡単に理解できた経験をお持ちの方も多いのではないでしょうか?

それと同じで、1冊の参考書を読んで理解できない事も、他の参考書とは異なる内容の解説を読むことで理解できる可能性があります。

なので、参考書は2冊持っておいた方が学習時に挫折しにくいというのが私の考えです。

特に上記の「スッキリわかるC言語入門」は、他の参考書とは違った切り口での解説が豊富で、他の参考書で理解できなかった内容に対して違った観点での解説を読むことができ、オススメです。題名の通り「なぜそうなるのか?」がスッキリ理解できるような解説内容にもなっており、C言語入門書としてもかなり分かりやすい参考書だと思います。

もちろんネット等でも色んな観点からの解説を読むことが出来ますので、分からない点は別の人・別の参考書の解説を読んで解決していきましょう!もちろん私のサイトも参考にしていただけると嬉しいです!

入門用のオススメ参考書は下記ページでも紹介していますので、こちらも是非参考にしていただければと思います。

https://daeudaeu.com/c_reference_book/

同じカテゴリのページ一覧を表示