Подтвердить что ты не робот

Преобразование фрагмента строки в int в Rust

Примечание Код в этом вопросе относится к версии Rust до 1.0, но ответы были обновлены для Rust 1.0.

У меня проблема с преобразованием строки в целое число.

fn main() {
    let input_text = io::stdin()
        .read_line()
        .ok()
        .expect("failed to read line");

    let input: Option<int> = from_str(input_text.as_slice());

    println!("{}", input);
}

Я ввожу номер на консоли (например, 42), и моя программа печатает None.

В документации говорится, что это нормальная ситуация, когда строка плохо отформатирована, но что не так с моей 42?

4b9b3361

Ответ 1

Вы можете вызвать str::parse(), но вам нужно убедиться, что работает read_line. Нам нужен читатель:

use std::io;

fn main() {
    let reader = io::stdin();
}

stdin читает глобальный буфер, который обрабатывает входной поток, а также реализует BufRead, который имеет метод read_line method. Это принимает изменяемый String в качестве входного буфера и считывает все байты из потока до тех пор, пока не будет достигнут байт новой строки и добавит их в буфер. Метод #expect() распаковывает Result; если это Err, он будет паниковать с сообщением и причиной.

use std::io;

fn main() {
    let reader = io::stdin();
    let mut input_text = String::new();
    reader.read_line(&mut input_text).expect("failed to read line");
}

Теперь у нас есть текст ввода, который мы хотим преобразовать в i32. Здесь str::parse() будет работать для нас, если мы дадим ему тип для синтаксического анализа. str::trim() необходимо, потому что read_line включает в себя байт новой строки в буфере

use std::io;

fn main() {
    let reader = io::stdin();
    let mut input_text = String::new();
    reader.read_line(&mut input_text).expect("failed to read line");
    let input = input_text.trim().parse::<i32>();
}

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

use std::io;

fn main() {
    let reader = io::stdin();
    let mut input_text = String::new();

    reader.read_line(&mut input_text).expect("failed to read line");

    let input_opt = input_text.trim().parse::<i32>();

    let input_int = match input_opt {
        Ok(input_int) => input_int,
        Err(e) => {
            println!("please input a number ({})", e);
            return;
        }
    };

    println!("{}", input_int);
}

Это компилируется без ошибок или предупреждений.

Ответ 2

Ввод включает в себя новую строку в конце, как описано в документации для read_line. Это приведет к сбою from_str(). Используя std::str::trim() и изменив это:

let input: Result<i32, _> = input_text.parse();

в это:

let input: Result<i32, _> = input_text.trim().parse();

похоже, работает.

Ответ 3

По состоянию на Rust 1.14 Язык программирования ржавчины имеет этот пример:

let guess: u32 = guess.trim().parse()
    .expect("Please type a number!");

Вы также можете снова использовать одно и то же имя переменной, и новый тип будет "теневым" старым типом:

use std::io;

fn main() {
    let mut input_text = String::new();

    io::stdin()
        .read_line(&mut input_text)
        .expect("failed to read line");

    let input: u32 = input_text.trim().parse()
        .expect("Please type a number!");
}

Ответ 4

Попробуйте следующее:

fn main() {
    let input_text = std::old_io::stdin()
        .read_line()
        .ok()
        .expect("failed to read line");
    let input_number: Option<i32> = input_text.trim().parse().ok();
    let number = match input_number{
        Some(num) => num,
        None => {
            println!("Wrong input data! Input a number.");
            return;
        }
    };
    println!("{}", number);
}

Ответ 5

Для преобразования строки в целое мы используем trim и parse. Метод trim() в Strings удалит любые пробелы в начале и конце нашей строки.

Это означает, что если мы наберем 5 и нажмем return, предположим, что выглядит так: 5\n.\N представляет 'новую строку, клавишу ввода. trim() избавится от этого, оставив нашу строку только с 5.

Метод parse() в строках анализирует строку на некоторый номер. Поскольку он может анализировать множество чисел, нам нужно дать Rust подсказку о точном типе нужного числа. Следовательно, пусть a_int: i32. Двоеточие (:) после угадывания говорит, что Руст собирался аннотировать его тип. i32 - целое число тридцать два бита. Мы используем метод expect() для сбоя, если theres ошибка.

 let a_int: i32 = input_1.trim().parse()
 .ok()
 .expect("Please type a number!");

Ref: