rust

Why do I get `ParseIntError { kind: InvalidDigit }` when parsing what seems to be a valid integer string?


I am writing a program that reads a file line-by-line, extracts all digits contained in each line (ignoring any other characters), interprets the resulting digits in each line as an integer, and prints the sum of the integers.

The file is the following:

1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet

And the expected output is 12 + 38 + 12345 + 7 = 12402

This is my attempt:

use std::fs;

fn main() {
    let contents = fs::read_to_string("day1.txt").expect("Should have been able to read the file");
    const ARRAY_REPEAT_VALUE: String = String::new();
    let mut number_array: [String; 4] = [ARRAY_REPEAT_VALUE; 4];
    let mut counter: usize = 0;

    for i in contents.lines() {
        let mut on_to_next: bool = false;
        let mut num1: char = '\0';
        let mut num2: char = '\0';
        for j in i.chars() {
            if j.is_numeric() {
                if on_to_next {
                    num2 = j;
                } else {
                    num1 = j;
                    on_to_next = true;
                }
            }
        }
        number_array[counter] = format!("{}{}", num1, num2);
        counter += 1;
    }

    let mut total: i32 = 0;
    for p in number_array {
        print!("-{}-\n", p.trim());
        let converted_number: i32 = p.trim().parse().unwrap();
        total += converted_number;
    }
    print!("{}", total);
}

But it fails with:

thread 'main' panicked at src/main.rs:35:54:
called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }

Why does it happen, and what can I do to fix this problem?


Solution

  • If you alter your debugging line to use debug output ({:?}):

    print!("-{:?}-\n", p.trim());
    

    You will notice that the last string slice you're trying to parse contains a nul character:

    -"12"-
    -"38"-
    -"15"-
    -"7\0"-
    

    Your .trim() here is doing exactly nothing; instead you could use .trim_end_matches('\0') to fix the immediate error:

    let converted_number: i32 = p.trim_end_matches('\0').parse().unwrap();
    

    There may still be other bugs in the program that make its output incorrect, but this fixes the specific error you are seeing.