RustArena

Step 4 of 7

Reading every line until the end

Often you don't know how many lines are coming: a log file, a list of orders, a CSV export. Then you read until the input ends. When the input comes from a file, that's the end of the file (often called EOF). When you type into a terminal, you signal the end with Ctrl+D (Linux and macOS) or Ctrl+Z then Enter (Windows).

use std::io;

fn main() {
    let mut count = 0;
    for line in io::stdin().lines() {
        let line = line.expect("failed to read a line");
        count += 1;
        println!("{count}: {line}");
    }
    println!("{count} lines");
}
apples
pears
plums
1: apples
2: pears
3: plums
3 lines

The classic form: lock() and BufRead

In existing code and older answers online you'll see this form. It does the same thing:

use std::io::{self, BufRead};

fn main() {
    let mut total = 0;
    for line in io::stdin().lock().lines() {
        let line = line.expect("failed to read a line");
        let n: i32 = line.trim().parse().expect("not a number");
        total += n;
    }
    println!("total: {total}");
}
10
20
12
total: 42

Skipping blank lines

Real input often has empty lines (a trailing blank line at the end of a file is very common). Skip them with continue:

use std::io;

fn main() {
    let mut names = 0;
    for line in io::stdin().lines() {
        let line = line.expect("failed to read a line");
        if line.trim().is_empty() {
            continue;
        }
        names += 1;
        println!("{names}. {}", line.trim());
    }
}
Ana

Ben
1. Ana
2. Ben

With read_line

read_line also tells you when the input has ended: it returns the number of bytes it read, and 0 means there was nothing left.

use std::io;

fn main() {
    let mut line = String::new();
    let mut longest = 0;
    loop {
        line.clear();
        let bytes = io::stdin().read_line(&mut line).expect("failed to read a line");
        if bytes == 0 {
            break;
        }
        let length = line.trim().chars().count();
        if length > longest {
            longest = length;
        }
    }
    println!("longest line: {longest} characters");
}
short
a bit longer
mid
longest line: 12 characters

Common mistakes

Your task

Whole numbers (possibly negative) arrive one per line, as many as there are. Skip blank lines (empty or only spaces). Print how many numbers there were and their total:

count: 4, total: 46

Challenge 2

Read log lines until the end of the input. Count all lines, and the lines that contain ERROR (in capitals, exactly). Print:

2 errors in 5 lines

Challenge 3

Read a list of names, one per line, until the end of input. Skip blank lines, trim each name, make it uppercase, and number the names from 1:

1. ANA
2. BEN
3. CY

Previous: Reading several lines Next: Several values on one line: split_whitespace