コンテンツにスキップ

Rustのbreak / continue

break と continue を使うと、ループを最後までまわさずに、途中で流れを変えられます。どちらも、loop、while、for の3種類のループすべてで同じように使えます。

break はループをその場ですぐに止めます。処理は、ループのすぐ後ろにあるコードへ移ります。

fn main() {
for i in 1..=10 {
if i == 5 {
break;
}
println!("{i}");
}
}

実行結果:

1
2
3
4
▶ 実際に試してみよう

範囲は10まであるのに、i が5になった瞬間にループは止まります。

continue はループ全体を止めるのではなく、今回の残りの処理を飛ばして、すぐに次の回へ進みます。

fn main() {
for i in 1..=10 {
if i % 2 == 0 {
continue; // 偶数は飛ばす
}
println!("{i}");
}
}

実行結果:

1
3
5
7
9
▶ 実際に試してみよう

偶数はすべて飛ばされます。continue が実行されると、println! を通らずに、ループはそのまま次の i の値へ進むからです。

ループの中に別のループを入れ子にしたとき、ふつうの break / continue が効くのはいちばん内側のループだけです。入れ子の内側から外側のループを抜けたいときは、外側のループにラベルを付けます('名前: のように書きます)。

fn main() {
'outer: for x in 1..=3 {
for y in 1..=3 {
if x * y > 4 {
break 'outer;
}
println!("{x} x {y} = {}", x * y);
}
}
}

実行結果:

1 x 1 = 1
1 x 2 = 2
1 x 3 = 3
2 x 1 = 2
2 x 2 = 4
▶ 実際に試してみよう

ラベルがなければ、break で止まるのは内側の y のループだけで、x のループは続いてしまいます。break 'outer; なら両方をいっぺんに止められます。完全に止めるのではなく、外側のループの次の回へ飛びたいときは、同じように continue 'outer; が使えます。

while ループでの continue の落とし穴

Section titled “while ループでの continue の落とし穴”

for ループでは、次の値は範囲から自動的に出てくるので、continue はいつでも安全です。while ループでは事情が違います。カウンタを更新するのは自分で、たいていは本体の一番下で更新します。continue がその更新を飛び越えてしまうと、カウンタはいつまでも変わらず、ループは永遠に回り続けます。

次のコードは3を飛ばそうとしていますが、固まってしまいます。実行しないでください。

fn main() {
let mut i = 0;
while i < 5 {
if i == 3 {
continue; // ❌ i を変えないまま先頭に戻ってしまう
}
println!("{i}");
i += 1;
}
}

i が3のとき、continue で条件のところに戻ります。i はまだ3のままなので、また continue が実行され、それが永遠にくり返されます。直し方は、continue するかもしれない処理より前にカウンタを更新することです。

fn main() {
let mut i = 0;
while i < 5 {
i += 1; // 先に更新しておけば、continue で飛ばされない
if i == 3 {
continue;
}
println!("{i}");
}
}

実行結果:

1
2
4
5
▶ 実際に試してみよう

i += 1 を先頭に移すと、数が1つずれます。このループは0から4ではなく1から5を表示するので、元の範囲が必要なら、開始値か条件を調整しましょう。さらに言えば、ただ数を数えるだけなら、範囲に対するforループを使えば、この問題はそもそも起きません。

1から10までの数を表示します。ただし、3の倍数はすべて飛ばしてください。ヒント:n % 3 == 0 のとき、その数は3の倍数です。continue を使って飛ばしましょう。

解答を見る
fn main() {
for n in 1..=10 {
if n % 3 == 0 {
continue;
}
println!("{n}");
}
}

実行結果:

1
2
4
5
7
8
10
▶ 実際に試してみよう

x と y の2つの for ループを入れ子にし、どちらも 1..=9 をまわします。x * y == 24 になる最初のペアを見つけて表示し、両方のループを止めてください。ヒント:外側のループにラベルを付けて、break 'outer; を使います。

解答を見る
fn main() {
'outer: for x in 1..=9 {
for y in 1..=9 {
if x * y == 24 {
println!("見つけました: {x} x {y} = 24");
break 'outer;
}
}
}
println!("探索を終了しました");
}

実行結果:

見つけました: 3 x 8 = 24
探索を終了しました
▶ 実際に試してみよう

break 'outer; をただの break; に変えてみましょう。すると内側のループしか止まらないので、探索が続き、4 x 6、6 x 4、8 x 3 も表示されます。

  • break はループをすぐに抜けます。
  • continue は今回の残りの処理を飛ばして、次の回へ進みます。
  • ラベル('outer:)を付けると、入れ子の内側から break / continue で外側のループを指定できます。
  • while ループでは、continue より前にカウンタを更新しましょう。そうしないと、ループが永遠に止まらなくなることがあります。

理解度チェック

1. ループの中で continue はどんな働きをしますか?

2. 入れ子のループから break で指定できるように、ループにラベルを付けるにはどう書きますか?

3. continue を使った while ループがいつまでも終わりません。いちばん考えられる原因は何ですか?

スコア: 0 / 3