C言語基礎|for文による繰り返しの中断と列挙

はじめに:for文は「回数で回す」だけじゃなく、「途中で止める」「条件で列挙する」も得意

for文って「0からnまで数える」みたいな定型だけに見えがちなんだけど、実はもう一段おもしろい使い方があります。

  • 入力を読んでいる途中で、ある合図が来たら中断する(break)
  • 条件に合うものだけを並べて表示する(列挙:enumeration)

この2つができると、for文が“ただのカウンタ”から実用的な処理の道具に変わります。
ここでは「繰り返しの中断」と「列挙」を、分かりやすい別プログラム例で押さえていきましょう。

サンプル1:for文で入力を読みつつ、指定値で中断する

目標歩数を最大日数分だけ入力し、0 を入力したらそこで入力終了するプログラムを例に解説をします。

  • break で for文を途中で抜けます
  • 実際に入力した回数で平均を割ります(ここが大事)

プロジェクト名:chap4-15-1 ソースファイル名:chap4-15-1.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

// 最大日数分の歩数を読み込み、0で入力終了。合計と平均を表示
#include <stdio.h>

int main(void)
{
    int days;
    printf("何日分の歩数を記録しますか:");
    scanf("%d", &days);

    printf("入力終了は 0 です。\n");

    int i;              // 実際に入力した回数としても使う
    int sum = 0;        // 合計歩数

    for (i = 0; i < days; i++) {
        int steps;
        printf("%d日目の歩数:", i + 1);
        scanf("%d", &steps);

        if (steps == 0) {
            puts("入力を終了します。");
            break;      // for文を中断
        }

        if (steps < 0) {
            puts("負の値は無効です。もう一度入力してください。");
            i--;        // この回はカウントしない(やり直し)
            continue;
        }

        sum += steps;
    }

    if (i == 0) {
        puts("有効な入力がありませんでした。");
        return 0;
    }

    printf("合計歩数:%d\n", sum);
    printf("平均歩数:%.1f\n", (double)sum / i);

    return 0;
}

実行例

何日分の歩数を記録しますか:5
入力終了は 0 です。
1日目の歩数:8000
2日目の歩数:10000
3日目の歩数:0
入力を終了します。
合計歩数:18000
平均歩数:9000.0

break / continue / for文の書式まとめ

今回登場する命令(文)と書式

名前書式何をする?
for文for (A; B; C) 文Aを1回実行 → Bが真なら文 → 文後にC → 再びB
break文break;いまいるループを強制終了して外へ出る
continue文continue;ループ本体の残りをスキップして次の繰り返しへ
if文if (式) 文条件が真のときだけ文を実行

break と continue の流れ(文章での図解)

ループ本体の中
  ├─ break;     → ループ全体を終了して外へ
  └─ continue;  → 本体の残りを飛ばして、次の繰り返しへ(C→Bへ)

この違いが分かると、入力チェックや例外処理がすごく書きやすくなります。

「for文終了後も使いたいカウンタ変数」は外で宣言する理由

さっきのサンプルでは i を for の外で宣言しています。

for内宣言と、for外宣言の違い

宣言場所ループ後に使える?どんなとき向いてる?
forの中for (int i=0; ... )使えないループ内だけで完結する
forの前int i; for (i=0; ... )使える実際に回った回数を後で使う

今回みたいに「実際に入力できた個数 i で平均を割る」みたいな用途があるなら、forの外に出しておくのが正解です。

サンプル2:列挙(条件に合う値をずらっと表示する)

ここからは「列挙」です。for文は 範囲を走査して、条件に合うものだけ表示するのが得意です。

例:n以下の「3の倍数」を列挙する

プロジェクト名:chap4-15-2 ソースファイル名:chap4-15-2.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

// 読み込んだ整数値以下の3の倍数を表示
#include <stdio.h>

int main(void)
{
    int n;
    printf("上限の値:");
    scanf("%d", &n);

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

    putchar('\n');
    return 0;
}

この for文の読み方

中身意味
Aint i = 33から開始
Bi <= nn以下の間だけ続ける
Ci += 33ずつ増やす

サンプル3:列挙(約数の表示)を素数の判定に応用

1 から n までを順に見て、偶数だけを表示する例です。

  • continue で「合わないものはスキップ」もできる
  • 「列挙」の基本形:範囲を回す
  • 条件に合うものだけ出す:if

プロジェクト名:chap4-15-3 ソースファイル名:chap4-15-3.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

// 1〜n を調べて、偶数だけ表示(列挙)
#include <stdio.h>

int main(void)
{
    int n;
    printf("上限の値:");
    scanf("%d", &n);

    for (int i = 1; i <= n; i++) {
        if (i % 2 != 0)
            continue;          // 奇数はスキップ
        printf("%d ", i);      // 偶数だけ表示
    }
    putchar('\n');

    return 0;
}

実行例

上限の値:15
2 4 6 8 10 12 14

列挙で continue を使うときの流れ

i を 2 から増やしながら候補を調べる
  ├─ 割り切れたら → break(これ以上調べなくていい)
  └─ 最後まで割れなければ → 素数

列挙(候補を順に調べる)と、中断(見つかったら止める)はセットで使われがちです。

演習問題

演習4-13:n 以下の 5 の倍数を表示せよ

整数 n を読み込み、n 以下の正の 5 の倍数を小さい順に表示せよ。

解答例

プロジェクト名:chap4-15-4 ソースファイル名:chap4-15-4.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

#include <stdio.h>

int main(void)
{
    int n;
    printf("整数値:");
    scanf("%d", &n);

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

    putchar('\n');
    return 0;
}

演習4-14:1 から n までの 3 乗を表示せよ

n を読み込み、1 から n までの各整数について 3乗を表示せよ。

解答例

プロジェクト名:chap4-15-5 ソースファイル名:chap4-15-5.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

#include <stdio.h>

int main(void)
{
    int n;
    printf("nの値:");
    scanf("%d", &n);

    for (int i = 1; i <= n; i++)
        printf("%dの3乗は%d\n", i, i * i * i);

    return 0;
}

演習4-15:# を指定個数表示し、4個ごとに改行せよ

整数 n を読み込み、# を n 個表示せよ。
ただし 4 個表示するごとに改行すること。n が 0 以下なら何も表示しない。

解答例

プロジェクト名:chap4-15-6 ソースファイル名:chap4-15-6.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

#include <stdio.h>

int main(void)
{
    int n;
    printf("何個 # を表示しますか:");
    scanf("%d", &n);

    if (n <= 0) return 0;

    for (int i = 1; i <= n; i++) {
        putchar('#');
        if (i % 4 == 0) putchar('\n');
    }
    if (n % 4 != 0) putchar('\n');

    return 0;
}