プログラミング

C言語超入門④ while文とfor文で繰り返そう

while、for、do-while、break、continueを使い、同じ処理を安全に繰り返す方法を学びます。

1から100まで表示したいとき、printfを100回書くのはつらいですよね。そこで使うのがループ(繰り返し)です。

ただ短く書くためだけではありません。「人数分のデータを読む」「正しい値が来るまで質問する」といった処理を、同じ考え方で作れるようになります。

今回はwhile、for、do-whileを順に比べます。if文の条件が読めれば始められます。短い例は、stdio.hを読み込んだプログラムのmain内で試してください。

1. whileは「条件を確認してから、もう1回」

#include <stdio.h>

int main(void) {
    int number = 1;

    while (number <= 3) {
        printf("%d\n", number);
        number++;
    }
    printf("終了時: %d\n", number);
    return 0;
}
1
2
3
終了時: 4

number++は、ここではnumber = number + 1と同じく1増やす操作です。ループは次の順番で進みます。

条件を見るときのnumber number <= 3 本体で行うこと
1 真 1を表示し、2へ更新
2 真 2を表示し、3へ更新
3 真 3を表示し、4へ更新
4 偽 本体へ入らず終了

最後の条件確認も数えると4回ですが、本体の実行は3回です。「何回表示したか」と「何回条件を調べたか」は同じとは限りません。

最初からnumber = 4なら、本体は一度も実行されません。whileは0回で終わる可能性がある繰り返しです。

2. 無限ループは「条件が変わるか」で見つける

先ほどのnumber++を消すと、numberはずっと1です。条件が真のままなので、1を表示し続けます。

こうした終わらない繰り返しを無限ループと呼びます。意図的に使う場面もありますが、今回の表示では間違いです。うっかり実行した場合は、ターミナルの停止操作、一般的にはCtrl+Cで止めます。

書くときは次の3点を言葉にしてみましょう。

  • 最初の値は何か
  • 何が変わって次へ進むか
  • どの状態で条件が偽になるか

また、while (number <= 3);のように条件の直後へ;を置くと、何もしない処理を繰り返してしまいます。字下げだけでなく、{ }と;の位置を見ます。

3. forは繰り返しの準備を1か所にまとめる

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

表示は先ほどと同じ1、2、3です。丸かっこの中をセミコロンで3つに分けています。

  1. int i = 1:最初に1回だけ行う準備
  2. i <= 3:本体の前に確認する条件
  3. i++:本体を実行した後の更新

文字の並びは「準備・条件・更新」ですが、実行する順は「準備 → 条件 → 本体 → 更新 → 条件」です。更新を先にしてから表示するわけではありません。

iは回数や位置に使う短い変数名です。意味が大切な場面ならdayやstudentIndexのような名前でも構いません。

0から始めるなら、条件も合わせる

for (int i = 0; i < 3; i++) {
    printf("%d回目\n", i + 1);
}

内部のiは0、1、2。表示は1、2、3回目です。3回繰り返したいからといってi <= 3にすると、0も含めて4回になります。

この1回のずれはオフバイワンエラーと呼ばれます。次回以降の配列では範囲外アクセスにつながるので、「最初と最後に本体へ入る値」を書き出す癖を付けておくと助かります。

4. 繰り返すたびに合計を育てる

int total = 0;

for (int i = 1; i <= 4; i++) {
    total = total + i;
}
printf("合計: %d\n", total);

結果は10です。

足す数i 足す前のtotal 足した後のtotal
1 0 1
2 1 3
3 3 6
4 6 10

totalは「これまでの合計」を覚える変数です。total += iと短く書くこともできます。

int total = 0;をループの中へ移すと、毎回0に戻ってしまいます。合計のように次の回へ持ち越す値は、外で準備しましょう。

また、totalを表示する行がループの中なら途中経過を毎回、外なら最後の結果を1回だけ表示します。置く場所によって目的が変わります。

5. do-whileは「まず1回やってから確認」

#include <stdio.h>

int main(void) {
    int number = 0;

    do {
        printf("1から10の整数: ");
        if (scanf("%3d", &number) != 1) {
            printf("数字として読めないため終了します。\n");
            return 1;
        }
    } while (number < 1 || number > 10);

    printf("%dを受け取りました。\n", number);
    return 0;
}

0、12、5の順に入力すると、最初の2つではもう一度質問し、5で抜けます。条件が後ろなので、質問は最低1回行われます。

最後のwhile (...);にはセミコロンが必要です。普通のwhileの直後に付けるのとは場所が違います。

この例は短い整数の練習用で、先頭の数値だけを読む場合があります。abcのように読めない入力では再試行せず終了します。同じ入力が残ったままscanfを繰り返すと、入力待ちにならず失敗し続けるためです。

文字を断って再入力できる仕組みは、成績管理の回で1行ずつ読み取る方法として扱います。

6. breakとcontinueはどこへ進む?

breakはループの外へ

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

表示は1、2、3、4。5になると表示する前に抜けます。

breakが抜けるのは、最も内側のループまたはswitchです。二重ループの外側までまとめて抜ける命令ではありません。

continueはその回の残りを飛ばす

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

表示は1、2、4、5です。3の回だけ表示を飛ばし、i++へ進みます。

whileでcontinueを使う場合は、次に条件確認へ戻ります。更新処理がcontinueより下にあると、その更新が飛ばされて無限ループになることがあります。迷ったら、最初はifの中へ必要な処理だけを書く形でも十分です。

繰り返しとジャンプの規則は、C11公開委員会草案の6.8.5と6.8.6に定義されています。

7. 練習:1から100のうち3の倍数を表示しよう

まず1から100までの数を順に見て、3で割り切れるときだけ表示してください。

模範解答

#include <stdio.h>

int main(void) {
    for (int number = 1; number <= 100; number++) {
        if (number % 3 == 0) {
            printf("%d\n", number);
        }
    }
    return 0;
}

解説

%は余りを求める記号です。3で割った余りが0なら3の倍数なので、ifの中で表示します。

1と2は飛ばし、3で最初の表示。最後は99で、100は条件に当てはまらないので表示されません。期待する個数は33個です。

別解としてfor (int number = 3; number <= 100; number += 3)なら、3、6、9と必要な数だけ進められます。最初の解答は「すべてを調べて選ぶ」、別解は「対象だけを作る」という違いです。

次の一歩

回数が見えているならfor、回数より終了条件を表したいならwhile、質問などを最低1回行うならdo-whileが候補です。どれが一番上等、という関係ではありません。

まず3回程度の小さな例で値を追ってから、大きな回数へ変えると、何が起きているか見失いにくくなります。

前の回 / 次の回:関数

← 記事一覧へ戻る