Rust: с нуля до своего органайзера Урок 12 из 20
Ветвления и выражения
Урок 12. Выбрать безопасное действие и получить значение из блока.
Текст переведён с помощью ИИ.
Предварительно: уроки 1–11. Если непонятны переменные, вернитесь к уроку 9.
Зачем это нужно
Урок 11 дал ответ true или false. Ветвление выбирает, какой участок программы выполнить по этому ответу. Представьте развилку: если путь закрыт, идём другим. Но компьютер не выбирает маршрут сам: проверяет записанные условия по порядку.
Вернёмся к числам урока 10. Если выполненных задач больше общего количества, вычитать их из u32 нельзя. Сначала проверим данные и только в подходящей ветви посчитаем остаток.
Запуск примера
Работаем в проекте organizer, созданном в уроке 6, в папке с Cargo.toml. Сохраните свою предыдущую работу отдельно. Замените весь src/main.rs первым примером ниже, сохраните файл и выполните cargo run в терминале этой папки. Как объяснялось в уроке 6, команда собирает и запускает программу. Остальные файлы менять не нужно; зависимости не добавляем. Каждый следующий полный пример также заменяет файл целиком. В блоке результата показан только вывод программы, без сообщений Cargo. Сначала предскажите его, потом запускайте.
Новая запись перед примером: if проверяет условие типа bool и выполняет следующий блок в { ... }, когда оно истинно. else if проверяет следующую возможность, else без условия выбирает оставшийся случай. В одной такой цепочке выполняется не больше одной ветви. В строке let urgent: bool = if ... { true } else { false }; сама цепочка выбирает значение; оба блока должны дать bool. Подробно разберём это после запуска.
fn main() {
let total: u32 = 7;
let done: u32 = 2;
if done > total {
println!("Ошибка: выполнено больше общего числа");
} else if done == total {
println!("Все задачи выполнены");
} else {
let remaining = total - done;
println!("Осталось: {remaining}");
}
let priority: u8 = 3;
let urgent: bool = if priority >= 3 { true } else { false };
println!("Срочно: {urgent}");
}
Осталось: 5
Срочно: true
Разбор
if читается «если»; за ним стоит условие типа bool, а в { ... } — блок действий. Если условие ложно, else if проверяет следующее. else означает «иначе» и не имеет собственного условия. В одной цепочке выполняется только первая подходящая ветвь. Последующие условия уже не проверяются.
При done = 2 первое и второе условия ложны: выполняется вычитание. При done = 7 сработает средняя ветвь. При done = 8 — первая, поэтому опасное вычитание не произойдёт. Отдельные два if не означают ту же цепочку: оба могут выполниться. Вокруг условия круглые скобки не обязательны, фигурные вокруг блока нужны. Число 1 не заменяет true.
Выражение даёт значение
Выражение вычисляет значение: total - done, сравнение и даже if. Инструкция выполняет действие; объявление let — пример инструкции. В строке let urgent: bool = if ...; выбрана одна из двух величин true и false.
Последнее выражение блока без ; становится его значением. Ветви, из которых хотим получить значение, должны согласовываться по типу: bool и число не подходят друг к другу. Здесь обе ветви возвращают bool. После всего объявления let точка с запятой нужна. Для этого простого случая можно короче: let urgent = priority >= 3;. Длинная форма нужна, чтобы увидеть устройство if.
Блок без завершающего выражения имеет значение (), называемое единичным значением (unit). Его тип тоже пишется (): полезного числа или логического ответа он не несёт. Это не ноль и не false. println! выводит текст, но не возвращает его как результат. В функции урока 14 мы встретим это снова.
Обычный блок тоже может вычислять значение:
fn main() {
let minutes = {
let preparation = 5;
preparation + 10
};
println!("{minutes}");
}
15
preparation — подготовка. Переменная доступна только внутри своих фигурных скобок, а вычисленное число получает внешнее имя minutes. Так область видимости из урока 9 отделяет промежуточный расчёт от результата.
Типичная ошибка
Лишняя точка с запятой убрала значение первой ветви. Этот отдельный пример намеренно даёт E0308:
fn main() {
let priority: u8 = 3;
let urgent: bool = if priority >= 3 { true; } else { false };
println!("{urgent}");
}
Уберите ; после true: обе ветви снова дадут bool. Не убирайте точку с запятой после всего объявления.
Опорная карта
Проверка данных → первая подходящая ветвь → действие или значение.
Проверьте понимание
- Сколько ветвей одной цепочки выполнится?
- Что даёт блок
{ 5 + 2 }, а что{ 5 + 2; }? - Где доступна переменная
remaining?
Сверка: не более одной; 7 и (); только в блоке else. При замене первого сравнения на >= равенство ошибочно станет считаться ошибкой данных.
Задание
Обязательное. Повторите проверку количества задач для total = 4, done = 6. Должна появиться только строка «Ошибка: выполнено больше общего числа». После этого проверьте done = 4 → «Все задачи выполнены» и done = 1 → «Осталось: 3». Никогда не вычисляйте разность до проверки.
Дополнительно. Объясните, что изменится, если первое условие записать как done >= total: какой случай больше не попадёт во вторую ветвь?
Подсказка
Сначала отклоните невозможные данные, затем проверьте равенство. Остаток вычисляйте только в else. Эталон показывает ошибочные входные данные, а не ошибку программы.
Эталон после самостоятельной попытки
fn main() {
let total: u32 = 4;
let done: u32 = 6;
if done > total {
println!("Ошибка: выполнено больше общего числа");
} else if done == total {
println!("Все задачи выполнены");
} else {
println!("Осталось: {}", total - done);
}
}
Ошибка: выполнено больше общего числа
Если вы нашли ошибку или опечатку в тексте статьи, то сообщите нам об этом
Комментарии (0)
Войдите, чтобы оставить комментарий →
Пока нет комментариев. Будьте первым.