C言語の基本|whileとforの使い分け

whileは条件で考える、forは回数で考える。
ループの形を選べるようになると、C言語のコードはぐっと読みやすくなる。

C言語では、同じ処理を何度も実行したいときにループを使います。
その代表的な書き方がwhile文とfor文です。

どちらも繰り返し処理を書くための構文なので、最初は「どちらを使っても同じでは?」と感じるかもしれません。
実際、同じ動きをwhileでもforでも書ける場面はたくさんあります。

ただし、実務や学習で大切なのは、単にループを書けることではありません。
「この処理にはwhileが自然」「この処理ならforの方が読みやすい」と判断できることです。

whileは、終了するタイミングが入力や状況によって変わる処理に向いています。
一方、forは、繰り返す回数や範囲がはっきりしている処理に向いています。

この違いを理解すると、コードの見た目から処理の目的が伝わりやすくなります。
自分が後で読み返したときも、他の人が読んだときも、ループの意図が分かりやすいコードになります。

図1:whileとforは目的で選ぶ

この図から分かること

whileとforは、どちらも繰り返し処理を書くための構文です。
しかし、選ぶ基準は同じではありません。

whileは「条件が成り立つ間、繰り返す」という考え方が中心です。
forは「何回繰り返すか」「どこからどこまで処理するか」という考え方が中心です。

つまり、ループを選ぶときは、まず次のように考えると分かりやすくなります。

  • 終了条件が入力や状況によって変わるならwhile
  • 回数や範囲が決まっているならfor
  • カウンタ変数を使って数える処理ならfor
  • 条件そのものを強調したいならwhile

for文の基本構文

for文は、繰り返しに必要な要素を丸括弧の中にまとめて書ける構文です。

for (初期設定式; 継続条件式; 再設定式) {
    文;
}

for文の丸括弧の中には、次の3つの要素があります。

部品役割実行されるタイミング
初期設定式カウンタ変数などを準備するループを始める前に1回だけ
継続条件式繰り返しを続けるか判定するループのたびに毎回
再設定式カウンタ変数などを更新するループ本体の処理が終わったあと

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

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

このfor文は、次のように読むことができます。

  • 最初にiを1にする
  • iが5以下の間は繰り返す
  • 1回処理が終わるたびにiを1増やす

この3つが1行にまとまっているため、for文はループの流れを一目でつかみやすい書き方です。

whileとforの本質的な違い

while文とfor文は、内部的には似たような動きをします。
しかし、コードを読んだときに伝わる印象が違います。

while文は、条件を中心にしたループです。

while (条件式) {
    文;
}

この形は、「この条件が真である間、処理を続ける」という意味がはっきり見えます。

一方、for文は、回数や範囲を中心にしたループです。

for (初期設定式; 継続条件式; 再設定式) {
    文;
}

この形は、「どこから始めて、どこまで続けて、どう更新するか」がまとまって見えます。

違いを簡単に整理すると、次のようになります。

判断ポイントwhileが合う場面forが合う場面
繰り返す回数が事前に分かるか分からないことが多い分かっていることが多い
終了条件が入力や状況で変わるか変わる場合に向いている変わらない場合に向いている
カウンタ変数が中心か必ずしも中心ではない中心になることが多い
コードの読みやすさ条件の意味が自然に読める初期化・条件・更新がまとまって見える

たとえば、ユーザーが0を入力するまで処理を続ける場合は、何回繰り返すかが事前に分かりません。
このような場合はwhileが自然です。

反対に、1から100まで順番に表示する場合は、繰り返す範囲がはっきりしています。
このような場合はforが自然です。

for文は3点セットを1行で見せられる

ループには、基本的に次の3つの要素が必要です。

  • 最初の値を用意する
  • 繰り返しを続ける条件を判定する
  • 1回ごとに値を更新する

while文でも、この3つを使ってループを書くことはできます。
ただし、while文ではそれぞれの場所が分かれやすくなります。

int i = 1;

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

この例では、iの初期化はwhile文の前にあります。
条件はwhileの丸括弧の中にあります。
更新はループ本体の中にあります。

同じ処理をfor文で書くと、次のようになります。

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

for文では、初期化、条件、更新が1行に集まっています。
そのため、「iを1から5まで増やしながら繰り返す」という流れがすぐに分かります。

図2:for文は初期化・条件・更新をまとめて見せる

この図から分かること

for文の強みは、ループに必要な要素を1行で確認できることです。
初期化、条件、更新がまとまっているため、カウンタを使った処理では特に読みやすくなります。

while文では、初期化や更新の位置が離れることがあります。
そのため、コードを読むときに「iはどこで用意されたのか」「iはどこで増えているのか」を探す必要があります。

短いプログラムでは大きな差に見えないかもしれません。
しかし、処理が長くなるほど、for文のまとまりは読みやすさにつながります。

whileで書いた処理はforに置き換えられることがある

カウンタ変数を使って決まった回数だけ繰り返す処理は、while文でもfor文でも書けます。

while文で書くと、次のようになります。

int i = 1;

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

for文で書くと、次のようになります。

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

この2つは、どちらも1から5までの整数を表示する処理です。
動きはほとんど同じです。

違うのは、処理の見せ方です。

while文は「iが5以下の間、繰り返す」という条件が前に出ます。
for文は「iを1から5まで1ずつ増やす」という範囲が前に出ます。

そのため、カウンタで数える処理では、for文の方が意図を伝えやすいことが多いです。

1からNまでの偶数だけを合計する処理

ここでは、同じ仕様のプログラムをwhile版とfor版で比べます。

作るプログラムの内容は、次のとおりです。

  • Nを入力する
  • 1からNまでの整数を順番に調べる
  • 偶数だけを合計する
  • 合計結果を表示する

1からNまで順番に調べるので、繰り返す範囲がはっきりしています。
このような処理は、for文がとても合いやすい題材です。

ただし、while文でも同じ処理を書くことはできます。
両方を見比べることで、whileとforの違いが分かりやすくなります。

1からNまでの偶数の合計をwhileで求めるプログラム

ファイル名:9_3_1.c

// whileで1からNまでの偶数の合計を求めるプログラム
#include <stdio.h>

int main(void)
{
    int n;
    int i = 1;
    int sum = 0;

    printf("Nを入力してください(1以上)> ");
    scanf("%d", &n);

    while (i <= n) {
        if (i % 2 == 0) {
            sum += i;
        }
        i++;
    }

    printf("1から%dまでの偶数の合計は%dです。\n", n, sum);

    return 0;
}
実行結果の例
Nを入力してください(1以上)> 10
1から10までの偶数の合計は30です。

このプログラムでは、変数iを1から始めています。
while文の条件はi <= nです。
つまり、iがn以下である間、繰り返し処理を続けます。

ループの中では、次の処理を行っています。

  • i % 2 == 0で偶数かどうかを調べる
  • 偶数ならsumにiを加える
  • 最後にi++でiを1増やす

たとえばNに10を入力した場合、1から10までを順番に調べます。
その中で偶数は2、4、6、8、10です。
これらを合計すると30になります。

while版では、iの初期化がループの前にあり、iの更新がループの中にあります。
そのため、ループ全体の動きを確認するには、少し広い範囲を見る必要があります。

1からNまでの偶数の合計をforで求めるプログラム

ファイル名:9_3_2.c

// forで1からNまでの偶数の合計を求めるプログラム
#include <stdio.h>

int main(void)
{
    int n;
    int sum = 0;

    printf("Nを入力してください(1以上)> ");
    scanf("%d", &n);

    for (int i = 1; i <= n; i++) {
        if (i % 2 == 0) {
            sum += i;
        }
    }

    printf("1から%dまでの偶数の合計は%dです。\n", n, sum);

    return 0;
}
実行結果の例
Nを入力してください(1以上)> 10
1から10までの偶数の合計は30です。

for版でも、処理の内容はwhile版と同じです。
1からNまでの整数を順番に調べ、偶数だけをsumに加えています。

違いは、カウンタ変数iの扱いです。

for (int i = 1; i <= n; i++)

この1行を見るだけで、次のことが分かります。

  • iは1から始まる
  • iがn以下の間は繰り返す
  • 1回終わるごとにiを1増やす

つまり、for版は「1からNまで順番に調べる」という意図がとても見えやすくなっています。
この例のように、回数や範囲が決まっている処理では、for文を使うとコードがすっきりします。

while版とfor版の読みやすさを比べる

同じ処理でも、while版とfor版では読みやすさが変わります。

比較する点while版for版
カウンタ変数の初期化ループの前に書くforの丸括弧内に書ける
条件式whileの丸括弧内に書くforの丸括弧内に書く
カウンタ変数の更新ループ本体の中に書くforの丸括弧内に書ける
向いている処理条件が中心の処理回数や範囲が中心の処理

while版は、条件の意味をそのまま表しやすい書き方です。
ただし、カウンタ変数を使う場合は、初期化と更新の位置が離れやすくなります。

for版は、カウンタ変数を使った繰り返しに向いています。
初期化、条件、更新がまとまっているため、ループの全体像をつかみやすくなります。

for文を日本語で読む

for文は、慣れないうちは少し詰まった書き方に見えるかもしれません。
しかし、日本語に分解すると分かりやすくなります。

for (int i = 1; i <= 5; i++)

このfor文は、次のように読めます。

  • iを1にして始める
  • iが5以下なら処理を続ける
  • 1回処理が終わるたびにiを1増やす

つまり、for文の丸括弧の中には、ループの準備、判定、更新が順番に並んでいます。

for文を読むときは、まず丸括弧の中を次の3つに分けて見ると理解しやすくなります。

for (準備; 判定; 更新)

この見方に慣れると、for文はかなり読みやすくなります。

カウンタ変数をどこで宣言するか

for文では、カウンタ変数をどこで宣言するかも大切です。
宣言する場所によって、その変数を使える範囲が変わります。

for文の中で宣言すると、その変数は基本的にfor文の中だけで使います。

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

この書き方では、iはfor文の中で使うための変数です。
ループが終わったあとの処理でiを使う必要がないなら、この形がすっきりしています。

一方、ループが終わったあとにもiを使いたい場合は、for文の前で宣言します。

int i;

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

printf("最後のiの値は%dです。\n", i);

この場合、iはfor文の外でも使えます。
そのため、ループ終了後の値を確認したい場合などに向いています。

ただし、特別な理由がなければ、カウンタ変数はfor文の中で宣言すると読みやすくなります。
そのループ専用の変数だと分かりやすいからです。

whileが自然に使える場面

for文は、回数や範囲が分かっている処理に向いています。
一方、while文は「いつ終わるか分からない処理」に向いています。

たとえば、次のような処理です。

  • 0が入力されるまで繰り返す
  • 正しい値が入力されるまで入力をやり直す
  • 条件を満たすまで処理を続ける
  • ファイルの終わりまで読み続ける

このような処理では、最初から繰り返し回数が決まっていません。
そのため、for文で書くよりもwhile文の方が自然です。

たとえば、0が入力されるまで繰り返す処理は、次のような形で書けます。

while (n != 0) {
    /* 入力と処理 */
}

この条件を見ると、「nが0ではない間は繰り返す」という意味がすぐに分かります。
while文は、終了条件をそのまま書けるところが強みです。

図3:whileは終了条件が状況で変わる処理に向いている

この図から分かること

while文は、回数ではなく条件を中心に考えるループです。
0が入力されるまで繰り返す処理では、何回入力されるかが事前に分かりません。

このような場合にfor文を使うと、初期化や更新の考え方が処理の目的と合わないことがあります。
while文なら、終了条件をそのまま条件式に書けるため、処理の意味が自然に伝わります。

whileとforを選ぶときの考え方

whileとforのどちらを使うか迷ったときは、最初に「何を基準に繰り返すのか」を考えます。

考え方選びやすいループ
1からNまで処理したいfor
配列を先頭から最後まで処理したいfor
決まった回数だけ表示したいfor
0が入力されるまで続けたいwhile
正しい入力が来るまでやり直したいwhile
条件を満たすまで続けたいwhile

ポイントは、回数で考えるか、条件で考えるかです。

回数や範囲が見えているならforを使うと読みやすくなります。
終了するタイミングが入力や状況に左右されるならwhileを使うと自然です。

どちらでも書ける場面はあります。
そのときは、コードを読んだ人にどちらの意図を伝えたいかで選ぶとよいです。

ループを選べるとコードの意図が伝わりやすくなる

while文とfor文は、どちらが上という関係ではありません。
それぞれ得意な場面が違います。

for文は、カウンタ変数を使って回数や範囲をはっきり見せたいときに向いています。
while文は、条件が成り立つ間だけ続ける処理を自然に表したいときに向いています。

C言語では、同じ処理を複数の書き方で表現できることがあります。
その中で読みやすい形を選べるようになると、プログラムの意図が伝わりやすくなります。

ループを書くときは、次のように考えると整理しやすくなります。

  • 回数が決まっているならfor
  • 範囲が決まっているならfor
  • 終了条件が入力や状況で変わるならwhile
  • 条件そのものを目立たせたいならwhile

この選び方に慣れると、whileとforをただ覚えるだけでなく、目的に合わせて使い分けられるようになります。