How can I read a single line from stdin?

Rust

Rust Problem Overview


I'm asking for the equivalent of fgets() in C.

let line = ...;
println!("You entered: {}", line);

I've read https://stackoverflow.com/questions/13579266/how-to-read-user-input-in-rust, but it asks how to read multiple lines; I want only one line.

I also read https://stackoverflow.com/questions/28528998/how-do-i-read-a-single-string-from-standard-input, but I'm not sure if it behaves like fgets() or sscanf("%s",...).

Rust Solutions


Solution 1 - Rust

In https://stackoverflow.com/questions/13579266/how-to-read-user-input-in-rust you can see how to iterate over all lines:

use std::io::{self, BufRead};

fn main() {
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        println!("{}", line.unwrap());
    }
}

You can also manually iterate without a for-loop:

use std::io::{self, BufRead};

fn main() {
    let stdin = io::stdin();
    let mut iterator = stdin.lock().lines();
    let line1 = iterator.next().unwrap().unwrap();
    let line2 = iterator.next().unwrap().unwrap();
}

You cannot write a one-liner to do what you want. But the following reads a single line (and is exactly the same answer as in https://stackoverflow.com/questions/28528998/how-do-i-read-a-single-string-from-standard-input):

use std::io::{self, BufRead};

fn main() {
    let stdin = io::stdin();
    let line1 = stdin.lock().lines().next().unwrap().unwrap();
}

You can also use the text_io crate for super simple input:

#[macro_use] extern crate text_io;

fn main() {
    // reads until a \n is encountered
    let line: String = read!("{}\n");
}

Solution 2 - Rust

If you truly want the equivalent to fgets, then @Gerstmann is right, you should use Stdin::read_line. This method accepts a buffer that you have more control of to put the string into:

use std::io::{self, BufRead};

fn main() {
    let mut line = String::new();
    let stdin = io::stdin();
    stdin.lock().read_line(&mut line).unwrap();
    println!("{}", line)
}

Unlike C, you can't accidentally overrun the buffer; it will be automatically resized if the input string is too big.

The answer from @oli_obk - ker is the idiomatic solution you will see most of the time. In it, the string is managed for you, and the interface is much cleaner.

Solution 3 - Rust

Read a single line from stdin:

    let mut line = String::new();
    std::io::stdin().read_line(&mut line)?; // including '\n'

You may remove '\n' using line.trim_end()

Read until EOF:

    let mut buffer = String::new();
    std::io::stdin().read_to_string(&mut buffer)?;

Using implicit synchronization:

use std::io;
fn main() -> io::Result<()> {
    let mut line = String::new();
    io::stdin().read_line(&mut line)?;

    println!("You entered: {}", line);
    Ok(())
}

Using explicit synchronization:

use std::io::{self, BufRead};

fn main() -> io::Result<()> {
    let stdin = io::stdin();
    let mut handle = stdin.lock();

    let mut line = String::new();
    handle.read_line(&mut line)?;

    println!("You entered: {}", line);
    Ok(())
}

If you interested in the number of bytes e.g. n, use:
let n = handle.read_line(&mut line)?;
or
let n = io::stdin().read_line(&mut line)?;

Try this:

use std::io;
fn main() -> io::Result<()> {
    let mut line = String::new();
    let n = io::stdin().read_line(&mut line)?;

    println!("{} bytes read", n);
    println!("You entered: {}", line);
    Ok(())
}

See doc

Solution 4 - Rust

if you want to leave the for-loop at some point

use std::io::{self, BufRead};

fn main() {
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        match line {
            Err(_) => break,    // with ^Z
            Ok(s) => println!("{}", s),
        }

    }
    println!("fin");
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsashoalmView Question on Stackoverflow
Solution 1 - Rustoli_obkView Answer on Stackoverflow
Solution 2 - RustShepmasterView Answer on Stackoverflow
Solution 3 - RustwasmupView Answer on Stackoverflow
Solution 4 - RustKaplanView Answer on Stackoverflow