I'm asking for the equivalent of fgets() in C.
let line = ...;
println!("You entered: {}", line);I've read How to read user input in Rust?, but it asks how to read multiple lines; I want only one line.
I also read How do I read a single String from standard input?, but I'm not sure if it behaves like fgets() or sscanf("%s",...).
6 Answers
In 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 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");
} 4 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.
0Read 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)?;
orlet 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
Starting with Rust 1.62, you can use Stdin::lines() to get one line (of input) using only one line (of code):
fn main() { let line = std::io::stdin().lines().next().unwrap().unwrap();
}Although Stdin::lines() can be used for a single line, it would typically be used for getting multiple. It simplifies this use case so that it is no longer necessary to worry about lifetimes and locking:
fn main() { for line in std::io::stdin().lines() { println!("line: {}", line.unwrap()); }
} 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");
} You can roll your own macro.
macro_rules! read_line { () => { { let mut str = String::new(); std::io::stdin().read_line(&mut str).expect("!"); str } };
}
fn main () { println!("What is your name?"); let name = read_line!(); println!("Hello {}.", name.trim());
}