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 ofIterator::position
and manual slicing. - Replaced the use of
as i32
byi32::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 usingFrom
/TryFrom
(orInto
/TryInto
) whenever possible, rather thanas
.
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 characterlet pos: usize = math_str.chars().position(|ch| match ch {'+' | '-' | '*' | '/' | '=' => true,_ => false}).expect("invalid operator, expected +, -, *, / or =");// extract the two numbers from the stringlet 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!(),
- }
- }