Menu
Coddy logo textTech

Оператор вопросительного знака '?'

Часть раздела Logic & Flow путешествия по Rust на Coddy — урок 46 из 66.

При работе с функциями, которые возвращают Result, вам часто нужно обрабатывать ошибки, либо разбираясь с ними локально, либо передавая их выше в вызывающую функцию. Rust предоставляет элегантный оператор для этого распространенного паттерна: оператор вопросительного знака ?.

Оператор ? предоставляет чистый способ распространения ошибок без написания многословных выражений match. Когда вы ставите ? после Result, он автоматически извлекает значение Ok или немедленно возвращает Err из текущей функции:

fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
    let number = s.parse::<i32>()?; // Если парсинг не удался, вернуть ошибку
    Ok(number * 2) // Если успешно, удвоить число
}

Это эквивалентно написанию полного оператора match, но гораздо более лаконично. Если s.parse::<i32>() возвращает Ok, оператор ? извлекает значение и присваивает его number. Если он возвращает Err, оператор ? немедленно возвращает эту ошибку из всей функции.

Оператор ? может использоваться только в функциях, которые возвращают Result (или Option), так как он должен иметь возможность возвращать ошибку.

challenge icon

Задание

Легко

Вы получите два входных значения. Первое значение — это строка, которую необходимо преобразовать в целое число, и второе значение — это еще одна строка, которую также необходимо преобразовать в целое число. Создайте функцию с именем add_numbers, которая принимает два строковых среза в качестве параметров и возвращает Result<i32, std::num::ParseIntError>. Внутри функции используйте оператор ? для парсинга обеих строк и верните их сумму, обернутую в Ok. Вызовите функцию с двумя входными значениями и обработайте результат с помощью match.

Требования:

  • Прочитайте первый ввод (первое число как строку) и удалите лишние пробелы
  • Прочитайте второй ввод (второе число как строку) и удалите лишние пробелы
  • Создайте функцию add_numbers, которая принимает два параметра типа &str и возвращает Result<i32, std::num::ParseIntError>
  • Внутри функции преобразуйте первую строку в i32, используя оператор ?
  • Преобразуйте вторую строку в i32, используя оператор ?
  • Верните Ok(sum), где sum — это сумма обоих преобразованных чисел
  • Вызовите функцию с двумя входными строками
  • Используйте выражение match для обработки Result
  • В ветке Ok(value) выведите: Sum: [value]
  • В ветке Err(_) выведите: Parsing error

Ввод:

  • Первая строка: Строка, представляющая число (например, 15)
  • Вторая строка: Строка, представляющая другое число (например, 27)

Вывод:

  • Если обе строки являются допустимыми числами: Sum: [result]
  • Если любую из строк невозможно преобразовать: Parsing error

Шпаргалка

Оператор вопросительного знака ? предоставляет краткий способ распространения ошибок в функциях, которые возвращают Result.

При размещении после Result оператор ?:

  • Распаковывает значение Ok и продолжает выполнение
  • Немедленно возвращает Err из текущей функции, если возникла ошибка
fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
    let number = s.parse::<i32>()?; // Если парсинг не удался, вернуть ошибку
    Ok(number * 2) // Если успешно, удвоить число
}

Оператор ? может использоваться только в функциях, которые возвращают тип Result или Option.

Попробуйте сами

use std::io;

// TODO: Создайте здесь функцию add_numbers
// Она должна принимать два параметра &str и возвращать Result<i32, std::num::ParseIntError>


fn main() {
    // Чтение первого ввода
    let mut input1 = String::new();
    io::stdin().read_line(&mut input1).expect("Failed to read line");
    let input1 = input1.trim();
    
    // Чтение второго ввода
    let mut input2 = String::new();
    io::stdin().read_line(&mut input2).expect("Failed to read line");
    let input2 = input2.trim();
    
    // TODO: Вызовите add_numbers с input1 и input2
    // TODO: Используйте match для обработки Result
    // Выведите "Sum: [value]" для Ok(value)
    // Выведите "Parsing error" для Err(_)
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Logic & Flow