1. 计算器

计算器 学习卡片

任务说明

实现一个支持加、减、乘、除和括号的简单计算器,能够解析用户输入的数学表达式(如 2 + 3 * (4 - 1))并输出计算结果。程序从命令行读取表达式,解析后打印结果。

实现思路

采用递归下降解析法:将表达式文法定义为 expr → term (('+'|'-') term)*,term → factor (('*'|'/') factor)*,factor → number | '(' expr ')'。解析器从左到右扫描输入,按优先级递归处理,除法使用浮点运算,遇到除数为零或非法字符时抛出明确错误。

代码实现

import sys

class Calculator:
    def __init__(self, text):
        self.text = text.replace(' ', '')
        self.pos = 0

    def parse(self):
        if not self.text:
            raise ValueError("空表达式")
        result = self.expr()
        if self.pos != len(self.text):
            raise ValueError(f"无法解析的字符: '{self.text[self.pos]}'")
        return result

    def expr(self):
        value = self.term()
        while self.pos < len(self.text) and self.text[self.pos] in '+-':
            op = self.text[self.pos]
            self.pos += 1
            rhs = self.term()
            value = value + rhs if op == '+' else value - rhs
        return value

    def term(self):
        value = self.factor()
        while self.pos < len(self.text) and self.text[self.pos] in '*/':
            op = self.text[self.pos]
            self.pos += 1
            rhs = self.factor()
            if op == '*':
                value *= rhs
            else:
                if rhs == 0:
                    raise ZeroDivisionError("除数为零")
                value /= rhs
        return value

    def factor(self):
        if self.pos < len(self.text) and self.text[self.pos] == '(':
            self.pos += 1
            value = self.expr()
            if self.pos < len(self.text) and self.text[self.pos] == ')':
                self.pos += 1
                return value
            raise ValueError("缺少右括号")
        return self.number()

    def number(self):
        start = self.pos
        while self.pos < len(self.text) and (self.text[self.pos].isdigit() or self.text[self.pos] == '.'):
            self.pos += 1
        if start == self.pos:
            raise ValueError(f"位置 {self.pos} 处不是有效数字")
        return float(self.text[start:self.pos])

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print("用法: python calculator.py \"表达式\"")
        sys.exit(1)
    try:
        result = Calculator(sys.argv[1]).parse()
        # 若结果为整数则去掉小数点
        print(f"{result:g}")
    except (ValueError, ZeroDivisionError) as e:
        print(f"错误: {e}")
        sys.exit(1)

运行与验证

将上述代码保存为 calculator.py,在终端执行以下命令:

python calculator.py "2 + 3 * (4 - 1)"
python calculator.py "10 / 4"
python calculator.py "(1 + 2) * 3"

预期输出分别为 11、2.5、9。程序支持小数、嵌套括号与空格;输入非法字符、缺少括号或除数为零时,会输出以 错误: 开头的提示并退出。

判定标准

  • 加减乘除四则运算结果正确,乘除优先级高于加减;
  • 括号可改变运算顺序,支持嵌套括号;
  • 表达式含空格时能正常解析;
  • 非法输入(如 2+*3、(1+2、5/0)能给出明确错误信息而非崩溃。
表达式解析调用时序 main Calculator 解析方法 传入表达式字符串 expr() → term() → factor() 返回数值结果 打印结果 异常路径: 抛出 ValueError / ZeroDivisionError