Simple calculator app - thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ParseFloatError

I get this error, only at runtime. The program compiles okay and runs for several sets of inputs, but fails and returns this error on some of them (no particular pattern of input that causes the error).

What is the first number?
4
What is the second number?
5
What operation would you like to do [ + - / * ]?
*
4 5 *
Result of 4 * 5 = 20
What is the first number?
9
What is the second number?
2
What operation would you like to do [ + - / * ]?
*
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ParseFloatError { kind: Invalid }', src\main.rs:25:25
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: process didn't exit successfully: `target\debug\calculator.exe` (exit code: 101)

The program is a simple calculator app, as described here: Let's Learn Rust: Checkpoint, Create a Calculator App - YouTube

Code is below:

use std::io::{ stdin, stdout, Write};

fn main() {

    println!("Welcome to the calculator!");

    println!("--------------");

    let mut num1 = String::new();

    let mut num2 = String::new();

    let mut operator = String::new();

    

    loop {

        println!("What is the first number?");

        read(&mut num1);

        println!("What is the second number?");

        read(&mut num2);

        println!("What operation would you like to do [ + - / * ]?");

        read(&mut operator);

        

        let num1: f32 = num1.trim().parse().unwrap();

        let num2: f32 = num2.trim().parse().unwrap();

        let operator: char = operator.trim().chars().next().unwrap();

        println!("{} {} {}", num1, num2, operator);

        let ops = String::from("+-*/");

        if !ops.contains(operator) {

            println!("Unknown operator!");

            continue;

        }

        let result = match operator {

            '+' => num1 + num2,

            '-' => num1 - num2,

            '*' => num1 * num2,

            '/' => num1 / num2,

            _ => panic!("Error in operator")

        };

        println!("Result of {} {} {} = {}", num1, operator, num2, result);

    }

}

fn read(input: &mut String) {

    stdout().flush().expect("failed to flush");

    stdin().read_line(input).expect("failed to read line");

}

The read_line function does not clear the string, but instead appends to it. It also includes the newline character. The error happened when it tried to parse num1, which after trimming had the value 4\n9.

Thanks for the reply!

We are using the .trim() method:

let num1: f32 = num1.trim().parse().unwrap();

Why would it retain the newline character despite this? What would be a workaround to this?

trim removes leading and trailing whitespace - it does not remove whitespace in the middle of a string.

It sounds like you should be calling .clear() on the num1 and num2 strings in each iteration of the loop, so that they are empty when you read into them. Or alternatively you could move the creation of the strings into the loop, so each iteration uses a brand new string.

1 Like

Note that trim does not modify the string it is called on, rather it returns a sub-slice that does not include the surrounding whitespace. This is why it is still there the next iteration.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.