Skip to content

Code Exercise

use std::io;
use std::io::Write;
fn main() {
let mut typer = UserTyper::new(CommandLineComputer);
loop {
typer.type_expr();
println!("Result: {}", typer.compute());
}
}
trait Computer {
fn compute(&self, expr: &str) -> i32;
}
struct CommandLineComputer;
impl Computer for CommandLineComputer {
fn compute(&self, expr: &str) -> i32 {
let mut num1 = String::new();
let mut num2 = String::new();
let mut op: Option<char> = None;
for chr in expr.trim().chars() {
if chr.is_digit(10) {
if op.is_none() {
num1.push(chr);
} else {
num2.push(chr);
}
continue;
}
// fix: 2 ++ 3
match chr {
'+' | '-' | '*' | '/' if op.is_none() => op = Some(chr),
_ if chr.is_whitespace() => continue,
_ => panic!("Invalid character: {}", chr),
}
}
if num1.is_empty() || num2.is_empty() || op.is_none() {
panic!("Invalid expression: {}", expr);
}
let num1 = num1.parse::<i32>().unwrap();
let num2 = num2.parse::<i32>().unwrap();
let op = op.unwrap();
match op {
'+' => num1 + num2,
'-' => num1 - num2,
'*' => num1 * num2,
'/' => num1 / num2,
_ => unreachable!(),
}
}
}
struct UserTyper<T: Computer> {
computer: T,
expr: String,
}
impl<T: Computer> UserTyper<T> {
fn new(computer: T) -> Self {
Self {
computer,
expr: String::new(),
}
}
fn type_expr(&mut self) {
self.expr.clear();
print!("Please type an expression: ");
io::stdout().flush().expect("Failed to flush stdout");
io::stdin()
.read_line(&mut self.expr)
.expect("Failed to read line");
}
fn compute(&mut self) -> i32 {
self.computer.compute(&self.expr)
}
}