Step 5 of 7
Several values on one line: split_whitespace
Input often packs several values on one line: 3 4, ana 92, move 10 -5. split_whitespace() cuts a string into pieces wherever there's whitespace:
fn main() {
let line = " move 10 -5\n";
for part in line.split_whitespace() {
println!("[{part}]");
}
println!("{} parts", line.split_whitespace().count());
}
[move]
[10]
[-5]
3 parts
- Any run of spaces, tabs or newlines separates two pieces, and whitespace at the ends is ignored. So there's no need to trim first.
- Each piece is a
&strview into the line: nothing is copied. .count()counts the pieces, just as.chars().count()counts characters.
Numbers from one line
Parse each piece and collect the numbers in a Vec:
use std::io;
fn main() {
let mut line = String::new();
io::stdin().read_line(&mut line).expect("failed to read a line");
let mut nums = Vec::new();
for part in line.split_whitespace() {
let n: i32 = part.parse().expect("not a number");
nums.push(n);
}
println!("{} numbers: {:?}", nums.len(), nums);
println!("first + last = {}", nums[0] + nums[nums.len() - 1]);
}
4 8 15 16 23 42
6 numbers: [4, 8, 15, 16, 23, 42]
first + last = 46
When the format says there are exactly two values (like width height), read them as nums[0] and nums[1]. If a line has fewer values than expected, the index is out of bounds and the program panics; that's acceptable for input you trust, and step 7 shows how to handle input you don't.
You'll often see the loop above written in iterator style, which you'll learn in modules 26 and 27:
let nums: Vec<i32> = line.split_whitespace().map(|p| p.parse().expect("not a number")).collect();
Why not split(' ')?
split(' ') cuts at every single space. Two spaces in a row produce an empty piece "" between them, and parsing "" fails:
fn main() {
let line = "3 4";
for part in line.split(' ') {
println!("[{part}]");
let n: i32 = part.parse().expect("not a number");
println!("{n}");
}
}
[3]
3
[]
The panic message: not a number: ParseIntError { kind: Empty }. For values separated by whitespace, split_whitespace is the right tool. (split(',') is right for comma-separated values; module 18 covers splitting in depth.)
Common mistakes
- Using
split(' ')on input that might have double spaces, tabs or a trailing newline. - Parsing the whole line when it holds several values:
"3 4".parse::<i32>()fails withinvalid digit found in string(the space is the invalid digit). - Assuming the number of values.
nums[1]panics on a line with one value. Checknums.len()when it matters.
Your task
One line holds a rectangle's width and height, separated by whitespace. Print its area and perimeter:
area: 12
perimeter: 14
Challenge 2
One line holds one or more whole numbers (possibly negative). Print how many there are, the smallest and the largest:
count: 5, min: -2, max: 9
Challenge 3
Each line holds a player's name and a whole-number score (possibly negative), like ana 92. Read lines until the end of the input and print the best player. If two players tie, keep the one that came first:
best: cy with 95
Previous: Reading every line until the end Next: Reading all the input at once