Dialvive
Dialvive

Reputation: 386

How to get the result of read_line() as a String in Rust?

I'm trying to get a String from standard input:

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);
}

But conversion from usize to String seems to change contents to it's length:

          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

Upvotes: 2

Views: 6764

Answers (1)

Kroltan
Kroltan

Reputation: 5156

Please see the documentation, and you can see that read_line mutates the contents of its parameter (in your case, the empty string bound at buffer), putting the value read into it, and returns the length read. But you're unwrapping that result and converting that length to a string.

Instead, your function should look like:

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;
}

Or, even more idiomatically, not panicking when invalid input is provided:

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),
    }
}

In this variant, the caller is the one that decides how to handle errors.

Upvotes: 7

Related Questions