Цикл while и do-while в Rust 1.75: подробное руководство
Цикл while и do-while в Rust
Что такое цикл и зачем он нужен?
Представь, что тебе нужно 100 раз написать в тетради: «Я буду хорошо учиться». Писать это 100 раз вручную — очень скучно и долго. В программировании для таких повторяющихся действий существуют циклы. Цикл — это команда компьютеру: «Делай это снова и снова, пока не наступит определённое условие».
Сегодня мы познакомимся с двумя видами циклов: while и do-while. Они помогают повторять действия, когда мы не знаем заранее, сколько раз их нужно повторить. Например, робот-шахтёр собирает кристаллы, пока его сумка не наполнится — он не знает, сколько кристаллов ему встретится.
Цикл while
Цикл while работает очень просто: «Пока условие верно — делай действие». Как только условие становится ложным, цикл останавливается.
Синтаксис цикла while в Rust:
while условие {
// код, который будет повторяться
}
Важно: условие проверяется перед каждым выполнением тела цикла. Если условие сразу ложное, цикл не выполнится ни разу.
Пример 1: Обратный отсчёт
Доктор Элара Вэнс запускает машину времени с начальной координаты n и ведёт обратный отсчёт до 1.
use std::io;
fn main() {
println!("Введите начальную временную координату:");
let mut input = String::new();
io::stdin().read_line(&mut input).expect("Ошибка чтения");
let mut n: i32 = input.trim().parse().expect("Введите число");
println!("Запуск обратного отсчёта:");
while n > 0 {
println!("{}...", n);
n = n - 1; // уменьшаем число на 1
}
println!("Время пошло вперёд!");
}
Как это работает:
Пользователь вводит число (например, 5). Цикл проверяет: «5 > 0? Да!» — печатает 5, затем 4, 3, 2, 1. Когда n становится 0, условие n > 0 ложно, и цикл завершается.
Цикл do-while (или loop с проверкой в конце)
В Rust нет отдельного ключевого слова do-while, как в других языках. Но его можно сделать с помощью loop и break.
Главное отличие от while: тело цикла выполняется хотя бы один раз, а потом проверяется условие. Синтаксис:
loop {
// код, который выполняется
if !условие {
break; // выходим из цикла, если условие стало ложным
}
}
Пример 2: Секретный агент
Агент получает зашифрованные коды. Нужно продолжать их обрабатывать, пока не встретится код 0 (сигнал остановки). При этом первый код нужно обработать обязательно.
use std::io;
fn main() {
println!("Вводите числовые коды (0 — стоп):");
loop {
let mut input = String::new();
io::stdin().read_line(&mut input).expect("Ошибка чтения");
let code: i32 = input.trim().parse().expect("Введите число");
if code == 0 {
println!("Сигнал остановки получен. Миссия завершена.");
break; // выходим из цикла
}
println!("Обработан код: {}", code * 2); // шифруем код
}
}
В этом примере код обрабатывается до проверки условия, поэтому даже если сразу ввести 0 — программа сначала обработает его (умножит на 2), а потом остановится.
Разбор типичных задач
Задача 1: Робот-шахтёр
Робот собирает кристаллы. Каждый кристалл даёт случайное количество энергии от 10 до 30. Нужно собирать, пока энергия не станет ≥ 100.
use std::io;
fn main() {
let mut energy = 0;
let mut crystals_collected = 0;
println!("Робот-шахтёр начал сбор кристаллов!");
while energy < 100 {
// Ввод энергии от кристалла (имитируем сканирование)
println!("Введите энергию найденного кристалла (10-30):");
let mut input = String::new();
io::stdin().read_line(&mut input).expect("Ошибка");
let crystal_energy: i32 = input.trim().parse().expect("Число!");
energy += crystal_energy;
crystals_collected += 1;
println!("Собран кристалл! Энергия: {}. Всего: {}", crystal_energy, energy);
}
println!("Сумка полна! Собрано {} кристаллов. Энергия: {}", crystals_collected, energy);
}
Задача 2: Юный садовод
Алекс хочет узнать, через сколько дней росток достигнет нужной высоты. Если росток уже выше или равен цели — ответ 0 дней.
use std::io;
fn main() {
println!("Введите начальную высоту ростка (см):");
let mut input = String::new();
io::stdin().read_line(&mut input).expect("Ошибка");
let mut height: f64 = input.trim().parse().expect("Число!");
println!("Во сколько раз он растёт каждый день?");
input.clear();
io::stdin().read_line(&mut input).expect("Ошибка");
let growth_rate: f64 = input.trim().parse().expect("Число!");
println!("Какой высоты вы хотите его вырастить?");
input.clear();
io::stdin().read_line(&mut input).expect("Ошибка");
let target: f64 = input.trim().parse().expect("Число!");
let mut days = 0;
while height < target {
height *= growth_rate;
days += 1;
println!("День {}: высота {:.1} см", days, height);
}
println!("Росток достиг {:.1} см через {} дней!", height, days);
}
Частые ошибки новичков
- Бесконечный цикл: забыли изменить переменную в условии. Например, написали
while n > 0 { println!("{}", n); }безn = n - 1. Компьютер будет печатать вечно! - Ошибка на 1 (off-by-one): неправильное условие. Например, нужно >= 100, а написали > 100 — цикл закончится раньше.
- Путаница с типом данных: если переменная целая (
i32), а вы пытаетесь использовать дробные числа — Rust выдаст ошибку. - Забыли про
breakвloop: цикл сloopбезbreakбудет работать бесконечно.
Итоговый пример: Волшебная экспедиция
Вы находите Артефакт Силы. Он начинает светиться, и вы понимаете: нужно вводить заклинания (числа), пока их сумма не достигнет ровно 100. Если сумма станет больше 100 — артефакт перегреется и сломается!
use std::io;
fn main() {
println!("🔮 Артефакт Силы ждёт заклинаний!");
println!("Вводите числа. Сумма должна стать ровно 100.");
println!("Если превысите — артефакт сломается!");
let mut sum = 0;
loop {
println!("Текущая сила: {}. Введите заклинание:", sum);
let mut input = String::new();
io::stdin().read_line(&mut input).expect("Ошибка");
let spell: i32 = input.trim().parse().expect("Введите число!");
sum += spell;
if sum == 100 {
println!("🎉 Ура! Артефакт активирован! Сумма ровно 100!");
break;
} else if sum > 100 {
println!("💥 О нет! Артефакт перегрелся! Сумма стала {}!", sum);
break;
} else {
println!("Сила растёт... ({} ед.)", sum);
}
}
println!("Экспедиция завершена.");
}
Заключение
Циклы while и loop (do-while) — твои верные помощники, когда нужно повторять действия, но ты не знаешь точное количество повторений. Главное — не забывай менять условие внутри цикла, чтобы он не стал бесконечным! Практикуйся на задачах с роботами, садоводами и агентами — и ты быстро научишься управлять циклами в Rust.