Ad
Strings
Mathematics

This code:

  • Normalizes the input string by removing all whitespace characters.
  • Splits the normalized string by the operator character.
  • Parses both parts as 32-bit integers.
  • Pattern-matches on the operator character to carry out the correct calculation.

List of changes made:

  • Make use of str::split_once instead of Iterator::position and manual slicing.
  • Replaced the use of as i32 by i32::from to make clear that the conversion is lossless, can't fail and won't involve any wrap-around or saturation due to overflow/underflow.
    For these reasons, cargo clippy also favors using From/TryFrom (or Into/TryInto) whenever possible, rather than as.
Code
Diff
  • fn math(s: &str) -> i32 {
        // remove whitespace characters so all we have left are digits and the operator
        let math_str: String = s.chars().filter(|ch| !ch.is_whitespace()).collect();
    
        // split the string by the operator character
        let (num1, num2) = math_str
            .split_once(|ch: char| matches!(ch, '+' | '-' | '*' | '/' | '='))
            .expect("missing operator, expected `+`, `-`, `*`, `/` or `=`");
    
        // slice out the operator character we just splitted by
        let operator = &math_str[num1.len()..=num1.len()];
    
        // parse both operands as i32s
        let num1: i32 = num1.parse().expect("invalid first operand");
        let num2: i32 = num2.parse().expect("invalid second operand");
    
        // pattern-match the operator character
        match operator {
            "+" => num1 + num2,
            "-" => num1 - num2,
            "*" => num1 * num2,
            "/" => num1 / num2,
            "=" => i32::from(num1 == num2),
            _ => unreachable!(),
        }
    }
    • fn math(s: &str) -> i32 {
    • // remove whitespace characters so all we have left are digits and the operator
    • let math_str: String = s.chars().filter(|ch| !ch.is_whitespace()).collect();
    • // find the position of the operator character
    • let pos: usize = math_str
    • .chars()
    • .position(|ch| match ch {
    • '+' | '-' | '*' | '/' | '=' => true,
    • _ => false
    • })
    • .expect("invalid operator, expected +, -, *, / or =");
    • // extract the two numbers from the string
    • let num1: i32 = math_str[..pos].parse().unwrap();
    • let num2: i32 = math_str[pos + 1..].parse().unwrap();
    • match &math_str[pos..=pos] {
    • // split the string by the operator character
    • let (num1, num2) = math_str
    • .split_once(|ch: char| matches!(ch, '+' | '-' | '*' | '/' | '='))
    • .expect("missing operator, expected `+`, `-`, `*`, `/` or `=`");
    • // slice out the operator character we just splitted by
    • let operator = &math_str[num1.len()..=num1.len()];
    • // parse both operands as i32s
    • let num1: i32 = num1.parse().expect("invalid first operand");
    • let num2: i32 = num2.parse().expect("invalid second operand");
    • // pattern-match the operator character
    • match operator {
    • "+" => num1 + num2,
    • "-" => num1 - num2,
    • "*" => num1 * num2,
    • "/" => num1 / num2,
    • _ => (num1 == num2) as i32,
    • "=" => i32::from(num1 == num2),
    • _ => unreachable!(),
    • }
    • }