Step 6 of 7
Reading all the input at once
Sometimes it's simplest to read the whole input into one String first, then take it apart. io::read_to_string does that:
use std::io;
fn main() {
let input = io::read_to_string(io::stdin()).expect("failed to read input");
let mut total = 0;
let mut count = 0;
for word in input.split_whitespace() {
let n: i32 = word.parse().expect("not a number");
total += n;
count += 1;
}
println!("{count} numbers, total {total}");
}
3 4
5
6 7
5 numbers, total 25
io::read_to_string(io::stdin())reads everything up to the end of the input, newlines included, and returns it as aString(wrapped in aResult, so.expectagain).split_whitespaceon the whole input treats newlines like spaces, so you get every value no matter how the lines are laid out. Perfect when only the values matter.- When the lines matter,
input.lines()splits theStringinto lines (without the newlines), just likeio::stdin().lines()but with noResultto unwrap:
use std::io;
fn main() {
let input = io::read_to_string(io::stdin()).expect("failed to read input");
for line in input.lines() {
println!("{} -> {} words", line, line.split_whitespace().count());
}
}
the quick brown fox
jumps
over the dog
the quick brown fox -> 4 words
jumps -> 1 words
over the dog -> 3 words
You may also meet the older form io::stdin().read_to_string(&mut input), which needs use std::io::Read; (another trait, like BufRead).
Which way to read?
| Style | Good for |
|---|---|
read_line |
interactive programs that ask a question and wait for the answer |
io::stdin().lines() |
processing input line by line, however big (logs, streams) |
io::read_to_string |
inputs you want to see as a whole (puzzles, small files, tests) |
read_to_string keeps the whole input in memory. That's fine for kilobytes or megabytes; for a 10 GB log file, go line by line.
Common mistakes
- Parsing the whole input as one number. The input ends with a newline (and may hold several values), so
input.parse()fails. Useinput.trim()for a single value, orsplit_whitespace()for many. - Forgetting that the input might be empty. With no input,
read_to_stringgives an emptyString; a loop over it simply runs zero times. Make sure your program still prints something sensible.
Your task
Read the whole input: whole numbers (possibly negative) spread over any number of lines. Print their average with two decimals, or no numbers if there are none:
average: 5.00
Challenge 2
Write a tiny version of the Unix wc tool: read the whole input and print the number of lines, words and characters (count every character of the input, including the newlines):
lines: 2
words: 6
characters: 29
Challenge 3
Read the whole input and print its lines in reverse order (last line first):
third
second
first
Previous: Several values on one line: split_whitespace Next: Handling bad input with match