Step 3 of 7
Reading several lines
Each call to read_line reads the next line. To read two values, call it twice:
use std::io;
fn main() {
let mut name = String::new();
io::stdin().read_line(&mut name).expect("failed to read a line");
let mut age = String::new();
io::stdin().read_line(&mut age).expect("failed to read a line");
let age: u32 = age.trim().parse().expect("age must be a whole number");
println!("{} is {} years old", name.trim(), age);
}
Ana
29
Ana is 29 years old
read_line appends
You might try to reuse one String for every line. Remember that read_line adds to what's already in the String:
use std::io;
fn main() {
let mut line = String::new();
io::stdin().read_line(&mut line).expect("failed to read a line");
io::stdin().read_line(&mut line).expect("failed to read a line");
println!("{:?}", line);
line.clear();
io::stdin().read_line(&mut line).expect("failed to read a line");
println!("{:?}", line);
}
3
4
5
"3\n4\n"
"5\n"
After two reads the String holds both lines, and parsing "3\n4" fails. line.clear() empties the String (keeping its memory for reuse) so the next read starts fresh.
A helper function
Reading one number takes three lines. When you need it several times, put them in a function:
use std::io;
fn read_number() -> i64 {
let mut line = String::new();
io::stdin().read_line(&mut line).expect("failed to read a line");
line.trim().parse().expect("not a whole number")
}
fn main() {
let a = read_number();
let b = read_number();
println!("{a} + {b} = {}", a + b);
}
7
35
7 + 35 = 42
- There's no type annotation on
parsehere: the function's return typei64tells it what to produce. - Each call creates a fresh
String, so there's nothing to clear. - Small helpers like this keep
mainreadable. That's what teams expect in code review: name the repeated thing once.
A count, then that many lines
A very common input format puts the number of items on the first line:
use std::io;
fn read_number() -> i64 {
let mut line = String::new();
io::stdin().read_line(&mut line).expect("failed to read a line");
line.trim().parse().expect("not a whole number")
}
fn main() {
let n = read_number();
let mut total = 0;
for _ in 0..n {
total += read_number();
}
println!("total of {n} numbers: {total}");
}
3
10
20
12
total of 3 numbers: 42
Common mistakes
- Reusing a
Stringwithoutclear(): the second value is glued to the first. - Reading past the end of the input. When there are no more lines,
read_linereads nothing and leaves theStringempty, so parsing fails and the panic message ends withParseIntError { kind: Empty }. - Reading in the wrong order. Lines come in the order they were typed; read them in the same order the input format describes.
Your task
Read two whole numbers, one per line (they may be negative), and print their sum, difference (first minus second) and product:
sum: 12
difference: 4
product: 32
Challenge 2
The first line says how many scores follow; then come the scores, one per line (they may be negative). Print the highest one:
best: 97
Challenge 3
Read a word on the first line and a number n on the second, then print the word n times on one line, separated by single spaces:
go go go
n is at least 1.
Previous: From text to numbers: parse Next: Reading every line until the end