breakとcontinue
ループの途中で進路を変える
ここまでのループは、条件が偽になるまで最後まで回りきる形でした。実際の集計では、そうもいかない事情が出てきます。欠席した学生は平均に入れたくありませんし、入力の終わりの合図が来たらその場でやめたくなります。
この 2 つを引き受けるのが break と continue です。名前は似ていますが、やることはまったく違います。
breakは ループそのものを終わらせる。波カッコの外に出て、続きの処理へ進みますcontinueは その回だけを飛ばす。中身の残りを実行せず、次の回に進みます
for (i = 1; i <= 10; i++) {
scanf("%d", &score);
if (score == -1) {
continue; /* 欠席なので集計しない */
}
if (score < 0) {
break; /* 終わりの合図なのでやめる */
}
total += score;
}continue が飛ばすのはどこまでか
continue を実行すると、そこから下の中身はすべて飛ばされ、ループの次の回へ移ります。for なら更新の i++ はきちんと実行されるので、回数が狂うことはありません。
気をつけたいのは while との組み合わせです。while の中身の最後で次の入力を読んでいる場合、continue はその scanf も飛ばしてしまいます。条件に使う変数が更新されないまま次の回に入るので、そのまま無限ループになります。continue を使うときは、条件を進める処理より 前 に置いてあるかを必ず確かめてください。
break が抜けるのは1枚だけ
break が終わらせるのは、いま自分が入っている いちばん内側のループ 1 つだけ です。第3章の switch でも break を使いましたが、あれも同じで、自分を囲むいちばん近い switch を抜けています。次回学ぶ二重ループの内側で break を書いても、外側のループは回り続けます。
使いすぎない
break も continue も、読み手にとっては「ここで流れが飛ぶ」という負担です。条件式を書き直すだけで済むなら、そのほうが読みやすくなります。目安として、continue は「この回は対象外」とはっきり言えるとき、break は「もう続ける意味がない」ときに限ると、意図が伝わるコードになります。
/* continue を使わない書き方 */
if (score >= 0) {
total += score;
}
/* continue を使う書き方 */
if (score < 0) {
continue;
}
total += score;この程度の短さなら、上のように if で囲むほうが素直です。continue が効いてくるのは、対象外の条件が何種類もあって、それを最初にまとめて振るい落としたいときです。先に例外を片付けてしまえば、そこから下は「まともなデータだけが来る」と思って読めるので、右へ右へと深くなる入れ子を防げます。
なお break と continue は、いま実行中のループにだけ効きます。関数の途中で処理を打ち切る return とは別ものです。関数は次章で学びますが、break を書けば関数が終わるわけではない、という点だけ先に押さえておいてください。
では、欠席者を飛ばしながら受験者の点数だけを集計してみましょう。
要件
- for で最大10回まで読み込む
- -1 が来たら「2人目 欠席」の形で表示し、集計には入れない
- -1 以外の負の数が来たら、その場で読み込みをやめる
- 最後に「受験者は3人、合計は240点です」の形で表示する
入出力例
main(80, -1, 90, 70, -9) → "2人目 欠席
受験者は3人、合計は240点です"
main(-1, -1, -9) → "1人目 欠席
2人目 欠席
受験者は0人、合計は0点です"