[Avg. reading time: 6 minutes]
Input from user
Reading User Input in Rust (std::io)
User input in Rust is handled through the standard library module std::io. Most input operations return a Result<T, E> because I/O can fail. You must decide:
- Crash on error -> expect() or unwrap()
- Handle gracefully -> match or ?
(Use VSCode for demo)
Example 1
cargo new input_demo
cd input_demo
// Input String
use std::io;
fn main() {
println!("Please enter your name:");
let mut name = String::new();
io::stdin()
.read_line(&mut name)
.expect("Failed to read input");
println!("Welcome {}", name.trim());
}
- String::new() creates an empty growable string on the heap.
- read_line(&mut name):
- Takes a mutable reference.
- Appends input (including newline).
- Returns Result<usize>.
- .expect("..."):
- If Err, program panics with the message.
- If Ok, continues execution.
- .trim() removes trailing newline.
- read_line() keeps \n. Without trim(), output formatting looks messy.
Example 2
// Accept two numbers
use std::io;
fn main() {
println!("Enter First Number:");
let mut s1 = String::new();
io::stdin().read_line(&mut s1).expect("Invalid input");
let n1: u32 = s1.trim().parse().expect("Not a valid number");
println!("Enter Second Number:");
let mut s2 = String::new();
io::stdin().read_line(&mut s2).expect("Invalid input");
let n2: u32 = s2.trim().parse().expect("Not a valid number");
let result = n1 + n2;
println!("Result: {result}");
}
Example 3 - Better Version
use std::io;
fn read_number(prompt: &str) -> u32 {
loop {
println!("{prompt}");
let mut input = String::new();
io::stdin().read_line(&mut input).expect("Read failed");
match input.trim().parse::<u32>() {
Ok(num) => return num,
Err(_) => println!("Please enter a valid number."),
}
}
}
fn main() {
let n1 = read_number("Enter First Number:");
let n2 = read_number("Enter Second Number:");
println!("Result: {}", n1 + n2);
}
- No panic
- Keeps asking until valid input
- Real-world pattern