Shanraq.org Shanraq.org
Ветвления и выражения
IT

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. Не убирайте точку с запятой после всего объявления.

Опорная карта

Проверка данных → первая подходящая ветвь → действие или значение.

Проверьте понимание

  1. Сколько ветвей одной цепочки выполнится?
  2. Что даёт блок { 5 + 2 }, а что { 5 + 2; }?
  3. Где доступна переменная 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)

Пока нет комментариев. Будьте первым.