トラック6・🔀制御構造

breakとcontinueの使いどころ

読む目安 約11分・ゴール:break でループを打ち切り、continue で残りをスキップできるようになり、それぞれの副作用を避けられる

アプリでこのトピックを学ぶ(無料・登録不要)

このトピックの要点

探し物をしています。棚を端から見ていって、見つかったらそこでやめる。これがbreakです。仕分けをしています。対象外のものは飛ばして次へ。これがcontinueです。

break — いま入っているループ(または switch)をその場で抜ける。

continue — 本体の残りを飛ばして、次の周回へ進む。ループ自体は続く。

break から見ましょう。1から順に足していって、合計が50を超えた時点で打ち切ります。

#include <stdio.h>

int main(void) {
    int sum = 0;
    int i;                      // ループの外で宣言(後で使うため)

    for (i = 1; i <= 100; i++) {
        sum += i;
        if (sum > 50) {
            break;              // 条件を満たしたので打ち切り
        }
    }
    printf("%d まで足して %d になりました\n", i, sum);
    return 0;
}

1+2+…+10 = 55 で初めて50を超えるので、「10 まで足して 55 になりました」と出ます。ここで i をループの外で宣言しているのが要点です。中で宣言すると、抜けた後に i が消えていて「何周目で止まったか」を使えません。

次に continue です。3の倍数だけを表示します。

#include <stdio.h>

int main(void) {
    for (int i = 1; i <= 10; i++) {
        if (i % 3 != 0) {
            continue;           // 3の倍数でなければ飛ばす
        }
        printf("%d ", i);
    }
    printf("\n");
    return 0;
}

出力は 3 6 9。もちろん if (i % 3 == 0) { printf… } と書いても同じ結果ですが、飛ばしたい条件が3つ4つと増えてくると、continue で先に弾いてしまうほうが本体が浅くなって読みやすくなります。

ここから、実際によく踏む地雷です。whileの中の continue は、更新処理を置き去りにします。

#include <stdio.h>

int main(void) {
    int i = 0;

    while (i < 5) {
        if (i == 2) {
            continue;       // i++ に到達しない → 無限ループ
        }
        printf("%d ", i);
        i++;
    }
    return 0;
}

i が 2 になった瞬間、continue が i++ を飛ばします。i は永遠に 2 のまま、条件は永遠に真——無限ループです。forなら更新式は本体の外にあるので continue でも必ず実行されますが、while では更新も本体の一部なので飛ばされてしまいます。while + continue を書くときは、continue の前に更新を済ませるか、素直に for にしてください。

師範while の中の continue は、更新を置き去りにする。for の更新式は置き去りにされぬ。この差だけは、体で覚えよ

もうひとつ。break が抜けるのは、一番内側のループ1つだけです。二重ループの内側で break しても、外側は何事もなかったように回り続けます。外側も抜けたいときは、boolのフラグを立てて外側の条件でも見るのが定石です(次のトピックで実例を出します)。

最後に使いすぎの話を少し。continue や break が何か所にも散らばると、流れが目で追えなくなります。「例外的に飛ばす/打ち切る」を1〜2か所まで、が読みやすさの目安です。

まとめます。break は打ち切り、continue は次の周回へ。break が抜けるのは内側1つだけ。while の中の continue は更新を飛ばす。

アプリでこのトピックを学ぶ(無料・登録不要)

確認問題

確認問題 1

二重ループの内側で break を実行しました。どうなりますか。

for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        if (j == 1) {
            break;
        }
        printf("%d-%d ", i, j);
    }
}
  1. 内側のループだけを抜け、外側は残りも回る(出力は 0-0 1-0 2-0)
  2. 内側も外側もまとめて抜ける(出力は 0-0)
  3. 外側のループだけを抜ける(出力は何も出ない)
  4. コンパイルエラーになる
答えを見る

正解:A(内側のループだけを抜け、外側は残りも回る(出力は 0-0 1-0 2-0))

break が抜けるのは、いま自分がいる一番内側のループ1つだけです。ここでは j が 1 になった時点で内側を抜けますが、外側の i のループは残りもきちんと回ります。よって各 i について j == 0 のときだけ表示され、0-0 1-0 2-0 となります。外側も一気に抜けたいときは、bool のフラグを立てて外側の継続条件でも判定するのが定石です。

確認問題 2

continue の入ったループです。各周のおわりに sum がいくつになっているか、空欄を埋めてください。

#include <stdio.h>

int main(void) {
    int sum = 0;
    for (int i = 1; i <= 5; i++) {
        if (i % 2 == 0) {
            continue;
        }
        sum += i;
    }
    printf("%d\n", sum);
    return 0;
}
icontinueするか周回おわりのsum
1しない1
2する?
3しない?
4する4
5しない?
答えを見る

空欄の答え(上から順に):1、4、9

i % 2 == 0(偶数)のときだけ continue が働き、sum += i; を飛ばして次の周回へ進みます。だから sum に足されるのは奇数の 1・3・5 だけで、1 → 4 → 9 と積み上がり、最後に 9 が表示されます。continue した周では sum は前の値のまま変わらない、という点がポイントです。なお continue はループ自体を止めるわけではないので、i は最後の 5 まできちんと進みます。

「制御構造」の目次

  1. 流れを変える——制御構造の全体像
  2. if文——もしも、の分かれ道
  3. else if / else の分かれ道設計
  4. 条件式の罠——= と == の悲劇
  5. 論理演算子と短絡評価
  6. switch文とfallthrough
  7. for文——回数が決まった繰り返し
  8. while文——条件が決める繰り返し
  9. do-while文と入力チェック
  10. breakとcontinueの使いどころ
  11. ループのネストと九九表
  12. 無限ループとの付き合い方

もっと先へ:ポインタ・メモリ・ファイル入出力・セキュアコーディングを含む全26トラックと、段位検定・模試のフルセットは完全版に収録しています。

完全版の販売ページは準備中です。

ほかのトラック

📚 姉妹教材:手を動かして覚える Linux 教材 — Linuxとインフラの仕組みを地図で学ぶ

Web版