Avatar ·

Как преобразовать строку (String или &str) в число (int) в Rust?

Всем привет! Я только начал изучать Rust, перешёл с Python, и столкнулся с проблемой, которая меня поставила в тупик. Мне нужно прочитать число из стандартного ввода или из текстового файла и выполнить с ним арифметические операции. В Python это делается в одну строчку: `number = int(input())`. Но в Rust я получаю ошибки компиляции. Вот мой код, который не работает: ```rust use std::io; fn main() { let mut input = String::new(); io::stdin().read_line(&mut input) .expect("Не удалось прочитать строку"); let number: i32 = input; // Ошибка! Несоответствие типов println!("Введённое число: {}", number + 10); } ``` Компилятор выдаёт ошибку: `expected i32, found struct String`. Я понимаю, что `read_line` возвращает строку, а не число. Но как мне её преобразовать? Я пробовал использовать `parse()`, но получаю другую ошибку: `error[E0282]: type annotations needed`. Кто-нибудь может объяснить правильный способ конвертации строки в целое число в Rust? Желательно с обработкой ошибок, если пользователь введёт не число. Заранее спасибо! <<>>

Решение: метод parse() с явным указанием типа

В Rust нет неявного преобразования между строками и числами. Для конвертации используется метод parse(), который доступен для типа String и &str. Этот метод возвращает Result, поэтому нужно обработать возможную ошибку.

Вот правильный способ преобразования строки в целое число:

use std::io;

fn main() {
    let mut input = String::new();
    io::stdin().read_line(&mut input)
        .expect("Не удалось прочитать строку");
    
    // Удаляем символ новой строки и пробелы
    let trimmed = input.trim();
    
    // Преобразуем строку в i32 с обработкой ошибки
    let number: i32 = match trimmed.parse() {
        Ok(num) => num,
        Err(e) => {
            eprintln!("Ошибка преобразования: {}", e);
            return;
        }
    };
    
    println!("Введённое число: {}", number + 10);
}

Объяснение по шагам:

  • trim() — удаляет пробельные символы (включая перевод строки \n) с начала и конца строки. Без этого parse() может не сработать.
  • parse() — обобщённый метод, который пытается преобразовать строку в целевой тип. Тип вывода определяется контекстом (в нашем случае — аннотацией : i32).
  • match — обрабатывает результат: Ok(num) — успешное преобразование, Err(e) — ошибка (например, если введён текст).

Альтернативные способы указания типа:

// Через "turbofish" синтаксис
let number = trimmed.parse::<i32>();

// Через expect для паники при ошибке (не рекомендуется для продакшена)
let number: i32 = trimmed.parse().expect("Введите корректное число!");

Другие целочисленные типы:

Вы можете использовать любой целочисленный тип: i8, i16, i32, i64, u8, u32 и т.д. Для больших чисел подойдёт i64 или u64.

let small: u8 = "255".parse().expect("Слишком большое число");
let big: i64 = "9223372036854775807".parse().expect("Переполнение");

Преобразование числа обратно в строку:

Для обратной операции используйте метод to_string():

let num = 42;
let s = num.to_string(); // "42"

Этот подход гарантирует безопасность типов в Rust и предотвращает ошибки, связанные с неявным преобразованием, которые часто встречаются в других языках.

<<>>

Использование крейта anyhow для упрощения обработки ошибок

Если вы работаете над проектом, где нужно часто конвертировать строки в числа, рекомендую использовать крейт anyhow (или thiserror). Он позволяет избавиться от громоздких конструкций match:

use anyhow::{Result, Context};
use std::io;

fn read_number() -> Result<i32> {
    let mut input = String::new();
    io::stdin().read_line(&mut input)
        .context("Не удалось прочитать ввод")?;
    
    let number = input.trim()
        .parse::<i32>()
        .context("Введено не число")?;
    
    Ok(number)
}

fn main() -> Result<()> {
    let num = read_number()?;
    println!("Число: {}", num + 10);
    Ok(())
}

Преимущества:

  • Оператор ? автоматически пробрасывает ошибки наверх.
  • Контекстные сообщения помогают быстро понять, где произошла ошибка.
  • Код становится чище и ближе к стилю Python.

Добавьте anyhow = "1.0" в Cargo.toml и используйте этот подход для обработки ввода в реальных приложениях.