Shanraq.org Shanraq.org
Ввод из терминала: строка, пустой ответ и конец потока
IT

Rust: с нуля до своего органайзера Урок 34 из 35

Ввод из терминала: строка, пустой ответ и конец потока

Урок 34. Прочитать название задачи и различить пустую строку, конец ввода и ошибку чтения.

Текст переведён с помощью ИИ.

Предварительно: уроки 4, 21–22, 25 и 31–33. Если Result ещё неясен, повторите урок 32.

Образ и опорная карта

Представьте стойку приёма: человек может написать название, оставить строку пустой или закрыть окно приёма. Это три разных события. Стандартный ввод — поток текста, который программа получает обычно из терминала; другой процесс также может передать туда текст. Конец потока (EOF) означает, что больше данных не будет. Пустая строка после нажатия Enter — введённая строка, а не конец потока. Образ ограничен: read_line сообщает число байтов, а не видимых букв, и может вернуть ошибку чтения.

Пустой Stringread_line(&mut ...)Ok(0) / Ok(число) / Errtrim() → ответ. std::io::stdin() получает стандартный ввод; std::io — путь к средствам ввода и вывода стандартной библиотеки, :: из урока 28 связывает части пути. String::new() создаёт пустую строку. read_line(&mut line) добавляет введённую строку в неё, поэтому нужна изменяемая ссылка. Метод возвращает Result<usize, std::io::Error>: Ok(0) означает конец потока, Ok с положительным числом — сколько байтов прочитано, Err — чтение не удалось. usize — тип размера и индекса из уроков о массивах. trim() даёт &str без пробелов и перевода строки по краям; внутри названия пробелы сохраняются. Если после этого текст равен "", название пустое.

Первый ответ пользователя

Сохраните прежний src/main.rs проекта organizer, замените весь файл и выполните cargo run рядом с Cargo.toml. Другие файлы и зависимости не меняются. После приглашения введите Чтение и нажмите Enter: программа покажет Задача: Чтение. В терминале набранные вами символы могут отображаться отдельно; это не вывод println!.

Для автоматической проверки пример запускается с уже закончившимся пустым вводом. Поэтому блок результата ниже показывает ветку EOF; она воспроизводится, если передать программе пустой поток. При обычном интерактивном запуске вводите название, чтобы проверить другую ветку.

fn main() {
    let mut line = String::new();
    println!("Введите название:");
    match std::io::stdin().read_line(&mut line) {
        Ok(0) => println!("Ввод закончился"),
        Ok(_) => {
            let title = line.trim();
            if title == "" {
                println!("Пустое название");
            } else {
                println!("Задача: {title}");
            }
        }
        Err(_) => println!("Не удалось прочитать ввод"),
    }
}
Введите название:
Ввод закончился

Нажатие Enter без текста идёт в Ok(_), после trim() название пустое и появляется Пустое название. Конец ввода идёт в Ok(0); повторять чтение после него без новой причины не нужно. trim() также убирает пробелы в начале и конце названия, что может быть желательным для задач, но для других данных правило надо выбирать отдельно. Обработка здесь одной строки — ещё не полный цикл команд органайзера.

Нельзя считать EOF пустым названием

Проверьте три наблюдения отдельно: введённое Чтение, пустая строка с Enter и отсутствие данных в потоке. Если смешать Ok(0) и Ok(_), программа начнёт просить название даже тогда, когда источник ввода уже закрыт. Ошибку Err тоже не превращайте молча в пустую задачу. Для пользовательских данных не применяйте .unwrap() к read_line.

Проверка понимания

  1. Почему line объявлена с mut?
  2. Что отличает Ok(0) от Enter на пустой строке?
  3. Удаляет ли trim() пробел между двумя словами?

Проверьте: read_line меняет строку; Ok(0) — конец потока, Enter даёт прочитанный перевод строки; внутренний пробел остаётся. Воспроизведите опорную карту без страницы.

Задание

Обязательное. Прочитайте одно название из стандартного ввода. При EOF покажите Больше ввода нет, при пустом после trim() названии — Нужно название, при удачном непустом вводе — Добавить: НАЗВАНИЕ, где название взято из ввода. При Err покажите Ошибка чтения. Испытайте все три обычных случая; для EOF завершите поток ввода способом вашей оболочки или подайте пустой файл.

Граница. Введите Мой план и убедитесь, что пробел между словами остаётся.

Подсказка

В match сначала поставьте Ok(0), затем Ok(_), затем Err(_). Внутри Ok(_) получите let title = line.trim(); и сравните его с пустым текстом.

Эталон после попытки

fn main() {
    let mut line = String::new();
    match std::io::stdin().read_line(&mut line) {
        Ok(0) => println!("Больше ввода нет"),
        Ok(_) => {
            let title = line.trim();
            if title == "" {
                println!("Нужно название");
            } else {
                println!("Добавить: {title}");
            }
        }
        Err(_) => println!("Ошибка чтения"),
    }
}
Больше ввода нет

Эталонный вывод показан для пустого потока; при Мой план будет Добавить: Мой план. Официальная документация read_line.

Предыдущий урок · Оглавление · Следующий урок

Если вы нашли ошибку или опечатку в тексте статьи, то сообщите нам об этом

Комментарии (0)

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