Char not working with if statement

Trying to make a simple calculator but no matter what I do it always returns 0. The only way it can return 0 is if the match statement doesn't find a possible match for the choice char variable. But that shouldn't be happening because the input always contains a match like 20 + 20 or 10 - 2. Which means that choice somehow isn't being assigned the correct value in the if/else statement. Why?

fn main() {
    const DIGITS: &str = "0123456789";
    const OPERATORS: &str = "-+*/";
    let mut string: String = String::new();
    let mut snum1: String = String::new();
    let mut snum2: String = String::new();
    let mut choice: char = ' ';

    let mut has_choice = false;

    let mut num1: i32;
    let num2: i32;

    input!(&mut string);
    
    for i in string.chars(){
        for j in DIGITS.chars(){
            if i == j && has_choice == false{
                snum1.push(i); 
            }
            if i == j && has_choice == true{
                snum2.push(i); 
            }
        }
        for n in OPERATORS.chars(){
            if i == n{ 
                has_choice = true; 
            
                choice = i; 
            } 
            else{ 
                choice = i; 
            }
        }
    }
    num1 = snum1.parse::<i32>().unwrap();
    num2 = snum2.parse::<i32>().unwrap();
    num1 = match choice{
        '-' => sub(&num1, &num2),
        '+' => add(&num1, &num2),
        '*' => mul(&num1, &num2),
        '/' => div(&num1, &num2),
        _ => 0
    };
    print!("Your result is {}", num1);
}
fn sub(num1: &i32, num2: &i32) -> i32{ 
    *num1 - *num2 
}
fn add(num1: &i32, num2: &i32) -> i32{ 
    *num1 + *num2 
}
fn mul(num1: &i32, num2: &i32) -> i32{ 
    *num1 * *num2 
}
fn div(num1: &i32, num2: &i32) -> i32{ 
    *num1 / *num2
}
#[macro_export]
macro_rules! input{
    ($x:expr) => {
    std::io::stdin().read_line($x).unwrap(); 
    }
}

Your program is misbehaving and it is not giving you enough information to understand why. You should fix this by changing the program so that it gives more information. Furthermore, you say that “that shouldn't be happening”; if your Rust code encounters something that shouldn’t happen — not just incorrect input, but an apparently impossible situation — the proper course of action is to panic, not to return invalid results. So, change the last arm of your match choice from

        _ => 0

to

        _ => panic!("unexpected operator {choice:?}")

Now, when you run the program, instead of just printing 0, it will print what value choice had that didn't match, and exit. If you then think about how that value could possibly have gotten into choice, you will be able to find the bug in your program.

Answer

In your input loop, you assign choice = i; whether or not i matches anything. Therefore, choice is always the last character of the line — which is \n, and of course is never the operator. If you delete the else { choice = i; } then your program will function correctly.

9 Likes

Thank you!!

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.