Break и continue в Rust
break и continue позволяют прервать цикл раньше, а не прогонять его до конца. Они одинаково работают во всех трёх видах циклов: loop, while и for.
break — выйти из цикла совсем
Заголовок раздела «break — выйти из цикла совсем»break сразу останавливает цикл, и выполнение переходит к тому, что идёт сразу после него:
fn main() { for i in 1..=10 { if i == 5 { break; } println!("{i}"); }}Вывод:
1234Хотя диапазон идёт до 10, цикл останавливается, как только i становится 5.
continue — перейти к следующему проходу
Заголовок раздела «continue — перейти к следующему проходу»continue пропускает остаток текущего прохода и сразу переходит к следующему, а не останавливает цикл целиком:
fn main() { for i in 1..=10 { if i % 2 == 0 { continue; // пропускаем чётные числа } println!("{i}"); }}Вывод:
13579Все чётные числа пропускаются: срабатывает 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 = 11 x 2 = 21 x 3 = 32 x 1 = 22 x 2 = 4Без метки break остановил бы только внутренний цикл по y, а x продолжил бы считать. break 'outer; останавливает оба сразу. continue 'outer; работает так же — если нужно не остановиться совсем, а перейти к следующему проходу внешнего цикла.
Ловушка continue в циклах while
Заголовок раздела «Ловушка continue в циклах while»В цикле 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}"); }}Вывод:
1245Перенос i += 1 наверх сдвигает числа на единицу: этот цикл выводит числа от 1 до 5, а не от 0 до 4, так что поправь начало или условие, если нужен прежний диапазон. А ещё лучше — если ты просто считаешь, используй цикл for по диапазону, и такая проблема в принципе не возникнет.
Практика
Заголовок раздела «Практика»1. Пропускаем числа, кратные 3
Заголовок раздела «1. Пропускаем числа, кратные 3»Выведи числа от 1 до 10, но пропусти все, что кратны 3. Подсказка: число кратно 3, когда n % 3 == 0. Пропусти его через continue.
Показать решение
fn main() { for n in 1..=10 { if n % 3 == 0 { continue; } println!("{n}"); }}Вывод:
124578102. Пара, которая в произведении даёт 24
Заголовок раздела «2. Пара, которая в произведении даёт 24»Используй два вложенных цикла 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
Что почитать
Заголовок раздела «Что почитать»- Метки циклов для устранения неоднозначности между несколькими циклами — книга «Язык программирования Rust»: официальное введение в метки с примером вложенного обратного отсчёта (перевод на русский).
- Вложенность и метки — Rust на примерах: короткий запускаемый пример с
break 'outerиcontinue 'outer(перевод на русский). - Loop Labels — The Rust Reference (на английском): точные правила, где можно использовать метки.
breakexpressions — The Rust Reference (на английском): как работаетbreak, в том числеbreakсо значением.continueexpressions — The Rust Reference (на английском): что делаетcontinueв каждом виде циклов.