use std::env;
use std::fmt;
#[derive(Debug)]
enum CalcError {
InvalidNumber(String),
InvalidOperator(String),
DivisionByZero,
MissingArguments,
}
impl fmt::Display for CalcError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
CalcError::InvalidNumber(s) => write!(f, "Invalid number: '{}'", s),
CalcError::InvalidOperator(s) => write!(f, "Unknown operator: '{}'", s),
CalcError::DivisionByZero => write!(f, "Cannot divide by zero"),
CalcError::MissingArguments => write!(f, "Usage: calc <num> <op> <num>"),
}
}
}
fn calculate(a: f64, op: &str, b: f64) -> Result<f64, CalcError> {
match op {
"+" => Ok(a + b),
"-" => Ok(a - b),
"*" | "x" => Ok(a * b),
"/" => {
if b == 0.0 {
Err(CalcError::DivisionByZero)
} else {
Ok(a / b)
}
}
"%" => Ok(a % b),
"^" => Ok(a.powf(b)),
_ => Err(CalcError::InvalidOperator(op.to_string())),
}
}
fn run() -> Result<(), CalcError> {
let args: Vec<String> = env::args().collect();
if args.len() != 4 {
return Err(CalcError::MissingArguments);
}
let a: f64 = args[1].parse().map_err(|_| CalcError::InvalidNumber(args[1].clone()))?;
let op = &args[2];
let b: f64 = args[3].parse().map_err(|_| CalcError::InvalidNumber(args[3].clone()))?;
let result = calculate(a, op, b)?;
println!("{} {} {} = {}", a, op, b, result);
Ok(())
}
fn main() {
if let Err(e) = run() {
eprintln!("Error: {}", e);
std::process::exit(1);
}
}