Перейти к содержимому

Break и continue в Rust

break и continue позволяют прервать цикл раньше, а не прогонять его до конца. Они одинаково работают во всех трёх видах циклов: loop, while и for.

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, и цикл сразу берёт следующее значение i, не выполняя println!.

Когда один цикл вложен в другой, обычные break/continue действуют только на самый внутренний цикл. Чтобы выйти из внешнего цикла изнутри вложенного, дай внешнему циклу метку (label) — она пишется как 'имя::

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; работает так же — если нужно не остановиться совсем, а перейти к следующему проходу внешнего цикла.

В цикле 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 до 5, а не от 0 до 4, так что поправь начало или условие, если нужен прежний диапазон. А ещё лучше — если ты просто считаешь, используй цикл for по диапазону, и такая проблема в принципе не возникнет.

Выведи числа от 1 до 10, но пропусти все, что кратны 3. Подсказка: число кратно 3, когда n % 3 == 0. Пропусти его через continue.

Показать решение
fn main() {
for n in 1..=10 {
if n % 3 == 0 {
continue;
}
println!("{n}");
}
}

Вывод:

1
2
4
5
7
8
10
▶ Попробуй сам

Используй два вложенных цикла for, x и y, оба по 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. Цикл while с continue никогда не заканчивается. Какая причина самая вероятная?

Результат: 0 / 3