Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I efficiently read in a single line of user input from the console? [duplicate]

Tags:

rust

I recently learned how to read input using io from the Rust documentation, but is there any 'simple' method for reading in console input? My roots are heavily dug into C++, so grabbing input from the console is as easy as std::cin >> var. But in Rust I'm doing:

for line in io::stdin().lines() {
    print!("{}", line.unwrap());
    break;
}

This reads input once, but the for loop seems like a really clumsy way to accomplish this. How can I easily do this?

like image 950
Syntactic Fructose Avatar asked Nov 30 '22 01:11

Syntactic Fructose


2 Answers

The answers above, as @freinn correctly points out, are now out of date. As of Rust 1.0, read_line() requires the caller to pass in a buffer, rather than the function creating & returning one. The following code requires Rust 1.26+ (further simplifying error handling).

Note the response is trimmed using trim_end(). This ensures the newline entered by the user will not be part of the response, which would split the greeting across two lines. Note also the example below is robust in the case the user does not provide a response:

use std::io::stdin;

type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;

fn main() -> Result<()> {
    println!("Hello, there!  What is your name?");

    let mut buffer = String::new();

    // `read_line` returns `Result` of bytes read
    stdin().read_line(&mut buffer)?;
    let res = match buffer.trim_end() {
        "" => "Ah, well I can respect your wish to remain anonymous.".into(),
        name => format!("Hello, {name}.  Nice to meet you!"),
    };
    println!("{res}");

    Ok(())
}
like image 156
U007D Avatar answered Jun 02 '23 23:06

U007D


io::stdin() is in fact a BufferedReader<> wrapping stdin. As you can see in the docs, BufferedReader gives a lot of ways to extract content.

You have notably :

fn read_line(&mut self) -> IoResult<String>

which will try to read a line from stdin (and possibly return an error). A simple code to read an isize from stdin would be :

let a: int = from_str(io::stdin().read_line().unwrap().as_slice()).unwrap()

but it does not any error handling and could easily fail.

A more explicit approach would require you to handle things more cleanly :

let a: isize = match from_str(
    match io::stdin().read_line() {
        Ok(txt) => txt, // Return the slice from_str(...) expects
        Err(e) => { /* there was an I/O Error, details are in e */ }
    }.as_slice() ) /* match from_str(...) */ { 
        Some(i) => i, // return the int to be stored in a
        None => { /* user input could not be parsed as an int */ }
    };
like image 24
Levans Avatar answered Jun 03 '23 00:06

Levans