C言語の基本|continue文の使い方

処理を終わらせず、不要な回だけをひと休み。continue文で、必要なデータだけを次の処理へ通そう。

ループでは、同じ処理を何度も繰り返します。しかし、すべての回で最後まで同じ処理を行いたいとは限りません。

たとえば、次のような場面があります。

  • 不正な入力値は合計に含めたくない
  • 条件に合わないデータは読み飛ばしたい
  • 特定の値だけ表示したくない
  • 無効なデータでは後続の計算を行いたくない

このように、ループそのものは続けながら、現在の回だけを途中で切り上げたいときに使うのがcontinue文です。

continue文が実行されると、その回で残っている処理は実行されません。その後、ループの種類に応じた位置へ移動し、次の繰り返しへ進みます。

break文がループ全体を終了する文であるのに対して、continue文は現在の回だけをスキップする文です。この違いを理解すると、入力チェックや集計処理をすっきり書けるようになります。

continue文とは

continue文は、for文、while文、do~while文などの繰り返し処理で使用する制御文です。

continue文が実行されると、その位置より後ろに書かれているループ内の処理を飛ばします。ただし、ループそのものは終了しません。

基本的な形は次のとおりです。

繰り返し処理 {
    処理1;

    if (スキップ条件) {
        continue;
    }

    処理2;
}

この処理は、次のように進みます。

  1. 処理1を実行する
  2. if文でスキップ条件を判定する
  3. 条件が真ならcontinue文を実行する
  4. 処理2を飛ばして次の繰り返しへ進む
  5. 条件が偽なら処理2を実行する

continue文で飛ばされるのは、現在の回に残っている処理だけです。次の回では、再びループ本体の処理が実行されます。

図1:continue文で現在の回だけをスキップする流れ

この図から分かること

continue文が実行されると、continue文より下にある処理は実行されません。

ただし、ループそのものは終了しないため、次の繰り返しへ進みます。次の回では、再びループ本体の先頭付近から処理が始まります。

continue文を使うときは、次の点を確認しましょう。

  • どの条件でcontinue文が実行されるか
  • continue文より後ろにどの処理があるか
  • 飛ばされた処理が次の回では再び実行されるか

continue文が向いている場面

continue文は、現在のデータを処理対象から外したい場合に向いています。

使用場面continue文の役割
入力チェック不正な入力では後続処理を行わない
集計処理条件に合わない値を合計や平均から外す
検索処理調べる必要のないデータを読み飛ばす
配列処理特定の要素だけ処理しない
表示処理条件に合わない値を表示しない

continue文を使うと、処理対象にしない条件を先に書けます。

if (処理対象ではない条件) {
    continue;
}

/* 処理対象だけがここへ到達する */
本来の処理;

この形では、continue文より後ろにある処理が正常なデータだけを扱います。条件分岐の入れ子を深くせずに書けることがあります。

if文と組み合わせて使う理由

continue文は、通常if文と組み合わせて使います。特定の条件が成立したときだけ、残りの処理を飛ばすためです。

たとえば、変数temperatureが0未満なら処理対象から外す場合は、次のように書けます。

if (temperature < 0) {
    continue;
}

temperatureが0未満ならcontinue文が実行されます。0以上なら条件が偽になるため、continue文より後ろにある処理へ進みます。

条件を付けずにcontinue文を書くと、毎回必ず残りの処理が飛ばされます。

for (int i = 0; i < 5; i++) {
    continue;
    printf("この文は実行されません。\n");
}

この例では、ループが繰り返されるたびにcontinue文が実行されます。その後ろにあるprintfには一度も到達しません。

そのため、continue文はスキップ条件を表すif文と組み合わせるのが基本です。

break文との違い

continue文とbreak文は、どちらもループの通常の流れを変える文です。ただし、実行後の動きは大きく異なります。

比較項目breakcontinue
現在の回の残り実行しない実行しない
次の繰り返し進まない進む
ループ全体終了する継続する
ループ後の処理すぐに進むループが終わってから進む
主な用途探索完了、終了入力、重大な異常無効値の除外、対象外データの読み飛ばし

処理を完全に終えたい場合はbreak文を使います。現在の回だけを無効にして、次のデータを処理したい場合はcontinue文を使います。

図2:break文とcontinue文の違い

この図から分かること

break文とcontinue文は、どちらも現在の位置より後ろにある処理を実行しない点では共通しています。

違いは、ループを続けるかどうかです。

  • break文はループ全体を終了する
  • continue文はループを続ける
  • break文の後はループ外の処理へ進む
  • continue文の後は次の繰り返しへ進む

不正なデータが1件あっても残りのデータを処理したい場合は、continue文が向いています。不正なデータを見つけた時点で処理全体を中止したい場合は、break文が向いています。

無効な測定値を合計から外す

ここでは、6回分の温度を入力し、0未満の値を無効な測定値として合計から外すプログラムを作ります。

有効な測定値だけを合計し、その件数も数えます。無効な値が入力されても、入力回数には含まれるため、for文は予定どおり6回実行されます。

0未満の測定値を除外して合計するプログラム

ファイル名:9_13_1.c

#include <stdio.h>

int main(void)
{
    int temperature;
    int total = 0;
    int valid_count = 0;

    for (int i = 1; i <= 6; i++) {
        printf("%d回目の温度を入力してください > ", i);
        scanf("%d", &temperature);

        /* 0未満の値は無効として、その回の集計を行わない */
        if (temperature < 0) {
            printf("無効な測定値のため、集計から外します。\n");
            continue;
        }

        /* 有効な測定値だけを集計する */
        total += temperature;
        valid_count++;
    }

    printf("有効な測定値は%d件です。\n", valid_count);
    printf("有効な測定値の合計は%dです。\n", total);

    return 0;
}
実行結果の例
1回目の温度を入力してください > 18
2回目の温度を入力してください > 21
3回目の温度を入力してください > -5
無効な測定値のため、集計から外します。
4回目の温度を入力してください > 20
5回目の温度を入力してください > -1
無効な測定値のため、集計から外します。
6回目の温度を入力してください > 23
有効な測定値は4件です。
有効な測定値の合計は82です。

プログラムの処理を順番に確認する

このプログラムでは、for文によって温度を6回入力します。

for (int i = 1; i <= 6; i++) {

入力されたtemperatureが0未満かどうかを、次のif文で判定します。

if (temperature < 0) {
    printf("無効な測定値のため、集計から外します。\n");
    continue;
}

temperatureが0未満なら、continue文が実行されます。その回では、次の2つの処理が飛ばされます。

total += temperature;
valid_count++;

そのため、負の値は合計に加えられず、有効件数にも含まれません。

continue文が実行された後もfor文は終了しません。更新式i++が実行され、次の入力へ進みます。

有効な値が入力された場合

temperatureが0以上なら、temperature < 0は偽になります。

その場合はcontinue文が実行されないため、次の集計処理へ進みます。

total += temperature;
valid_count++;

totalには有効な測定値が加算され、valid_countは1増えます。

実行例で合計される値は、次の4つです。

入力回入力値判定totalへの加算
1回目18有効18
2回目21有効21
3回目-5無効加算しない
4回目20有効20
5回目-1無効加算しない
6回目23有効23

有効な値の合計は、次の計算になります。

18 + 21 + 20 + 23 = 82

有効な測定値は4件なので、valid_countには4が入ります。

continue文を使わない書き方との比較

同じ処理は、continue文を使わずにif~else文で書くこともできます。

if (temperature < 0) {
    printf("無効な測定値のため、集計から外します。\n");
} else {
    total += temperature;
    valid_count++;
}

この書き方も正しく動作します。

continue文を使う場合は、無効なデータを先に除外し、その後に有効なデータの処理をまとめられます。

if (temperature < 0) {
    printf("無効な測定値のため、集計から外します。\n");
    continue;
}

total += temperature;
valid_count++;

2つの書き方には、次のような違いがあります。

書き方特徴
if~else文有効と無効の処理を2つのブロックに分ける
continue文無効な場合を先に飛ばし、通常処理を後ろにまとめる

どちらを使っても構いません。処理が短い場合はif~else文でも十分に読みやすくなります。通常処理が長く、対象外のデータを早めに除外したい場合はcontinue文が役立ちます。

for文でcontinue文を使った後の流れ

for文でcontinue文が実行されると、for文の更新式へ進みます。

for (初期化式; 継続条件式; 更新式) {
    処理;

    if (スキップ条件) {
        continue;
    }

    残りの処理;
}

処理の流れは次のようになります。

  1. ループ本体を実行する
  2. continue文を実行する
  3. その回の残りの処理を飛ばす
  4. for文の更新式を実行する
  5. 継続条件式を判定する
  6. 条件が真なら次の回へ進む

先ほどのプログラムでは、continue文が実行されてもi++は行われます。そのため、同じ入力回で止まり続けることはありません。

while文でcontinue文を使った後の流れ

while文でcontinue文が実行されると、すぐにwhile文の継続条件へ戻ります。

while (継続条件) {
    処理;

    if (スキップ条件) {
        continue;
    }

    残りの処理;
}

for文とは異なり、while文には専用の更新式がありません。カウンタ変数などの更新は、ループ本体の中に自分で書きます。

そのため、continue文より後ろに更新処理があると、更新されないまま条件判定へ戻ることがあります。

while文では更新処理の位置に注意する

次の書き方では、valueが負のときにcontinue文が実行されます。

while (i <= 5) {
    scanf("%d", &value);

    if (value < 0) {
        continue;
    }

    i++;
}

負の値が入力されると、i++を実行せずにwhile文の条件判定へ戻ります。

入力処理が毎回実行されるため、この例が直ちに無限ループになるとは限りません。しかし、iが入力回数を表す設計なら、負の値が入力された回ではカウンタが進まないため、予定した回数と動作がずれてしまいます。

カウンタを必ず進めたい場合は、continue文より前で更新します。

while (i <= 5) {
    scanf("%d", &value);
    i++;

    if (value < 0) {
        continue;
    }

    有効な値の処理;
}

continue文の前後に何が書かれているかによって、プログラムの動きが変わります。

図3:while文でcontinue文を使うときの更新位置

この図から分かること

while文には、for文のように自動的に実行される更新式がありません。

continue文より後ろに更新処理を書くと、スキップ条件が成立した回では更新処理も飛ばされます。その結果、カウンタが進まなかったり、継続条件に使う変数が変化しなかったりする可能性があります。

while文でcontinue文を使うときは、次の点を確認しましょう。

  • 継続条件に使っている変数はどこで更新されるか
  • continue文によって更新処理が飛ばされないか
  • 更新されない場合でも、いつか継続条件が偽になるか

do~while文でcontinue文を使った後の流れ

do~while文でcontinue文が実行されると、ループ末尾の継続条件へ進みます。

do {
    処理;

    if (スキップ条件) {
        continue;
    }

    残りの処理;
} while (継続条件);

continue文が実行されても、do~while文の末尾にある継続条件は判定されます。

ループごとの移動先を整理すると、次のようになります。

ループcontinue文を実行した後の移動先
for文更新式へ進む
while文継続条件の判定へ戻る
do~while文末尾の継続条件の判定へ進む

どのループでも現在の回の残りを飛ばす点は同じです。ただし、次に実行される位置が異なるため、特に更新処理の扱いに注意しましょう。

多重ループではどのループに作用するか

多重ループの内側でcontinue文を実行した場合、対象になるのはcontinue文を直接囲んでいる一番内側のループです。

for (int row = 1; row <= 3; row++) {
    for (int col = 1; col <= 3; col++) {
        if (スキップ条件) {
            continue;
        }

        処理;
    }
}

このcontinue文は、内側のcolを使うfor文の次の繰り返しへ進みます。外側のrowを使うfor文の次の回へ直接進むわけではありません。

多重ループでcontinue文を見つけたら、どのループに直接囲まれているかを確認しましょう。

continue文を使うときの注意点

continue文は便利ですが、増やしすぎると処理の流れを追いにくくなります。

注意点確認する内容
無条件で使わないその回の残りが毎回飛ばされてしまう
飛ばす処理を確認する必要な計算や更新まで飛ばしていないか
多用しすぎない次の回へ進む場所が増えると読みづらくなる
while文の更新に注意する条件変数が更新されず、終了できない可能性がある
多重ループに注意する一番内側のループに作用する
break文と区別するループを終了したいのか、次へ進みたいのかを考える

continue文は、不要なデータを早めに除外する目的で使うと分かりやすくなります。

読みやすいcontinue文を書くためのポイント

continue文を使うときは、何を処理対象から外すのかが分かるように書きましょう。

  • スキップ条件をif文で明確にする
  • continue文で飛ばされる処理を確認する
  • 通常の処理をcontinue文より後ろにまとめる
  • スキップする理由が分かるコメントを書く
  • continue文を必要以上に増やさない
  • while文では更新処理の位置を確認する
  • break文との役割の違いを意識する
  • 多重ループでは対象となるループを確認する

continue文は、ループを終わらせずに特定の回だけを処理対象から外すための文です。無効な入力や不要なデータを先に取り除き、必要な処理を分かりやすく並べたいときに役立ちます。