Как получить результат read_line () в виде строки в Rust?

Я пытаюсь получить String со стандартного ввода:

use std::io;

fn ask_nick() -> String {
    let reader = io::stdin();
    let mut buffer: String = String::new();

    let nickname: String = reader.read_line(&mut buffer).ok()
        .expect("ERRMSG").to_string();

        println!("OK: Hello {}!", &nickname);
        return nickname;
    }
}

fn main() {
    let nickname: String = ask_nick();
    println!("{}", nickname);
}

Но преобразование из usize в String, похоже, изменяет содержимое до его длины:

          INPUT:= John
EXPECTED OUTPUT:= OK: Hello John!
                  John
         OUTPUT:= OK: Hello 5!
                  5

          INPUT:= Doe
EXPECTED OUTPUT:= OK: Hello Doe!
                  Doe
         OUTPUT:= OK: Hello 4!
                  4

В чем именно заключается ваш вопрос? Что вы ожидаете от программы?

Tim Diekmann 13.09.2018 02:52

@TimDiekmann Я редактировал содержание вопроса. Как мне преобразовать reader.read_line (& mut buffer), который является usize, в строку, не изменяя ее содержимое на длину его содержимого?

Dialvive 13.09.2018 03:05

Лучший способ конвертировать usize в String - через to_string, точно так же, как вы это делаете. Какой у вас вопрос настоящий?

Shepmaster 13.09.2018 04:11

@Shepmaster Проблема заключается в путанице по поводу того, как работает read_line. OP ожидает, что функция вернет строку, но фактически возвращает количество прочитанных байтов и изменяет предоставленный буфер.

Peter Hall 13.09.2018 10:16
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
1
4
2 689
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Пожалуйста, посмотрите документация, и вы можете увидеть, что read_lineмутирует - содержимое своего параметра (в вашем случае, пустая строка, привязанная к buffer), помещает в него прочитанное значение и возвращает длина читать. Но вы разворачиваете этот результат и конвертируете эту длину в строку.

Вместо этого ваша функция должна выглядеть так:

fn ask_nick() -> String {
    let reader = io::stdin();
    let mut buffer: String = String::new();

    reader.read_line(&mut buffer)
        .ok()
        .expect("ERRMSG");

    println!("OK: Hello {}!", buffer);
    return buffer;
}

Или, что еще более идиоматично, не паниковать, когда предоставляется недопустимый ввод:

fn ask_nick() -> Result<String> {
    let reader = io::stdin();
    let mut buffer: String = String::new();

    match reader.read_line(&mut buffer) {
        Ok(_) => Ok(buffer),
        Err(e) => Err(e),
    }
}

В этом варианте вызывающий - тот, кто решает, как обрабатывать ошибки.

Если не считать неправильного использования переменной nickname после ее удаления (в вашем первом фрагменте), это правильно. Вам также не нужно передавать их по ссылке на макрос println, так как он все равно не станет владельцем.

Simon Whitehead 13.09.2018 03:45

@SimonWhitehead хороший улов! я на самом деле мысленно проигнорировал эту строчку случайно.

Kroltan 13.09.2018 04:08

Я думаю, вы могли бы заменить это последнее совпадение на reader.read_line(&mut buffer).map(|_| buffer), если хотите быть по-настоящему кратким :) Если только нет каких-то странностей с семантикой закрывающих ходов, которые я не учел, то есть!

Joe Clay 13.09.2018 10:32

Другие вопросы по теме