简单四则运算解析器题解 | 豆包MarsCode AI 刷题

90 阅读3分钟

简单四则运算解析器题解 | 豆包MarsCode AI 刷题

本题要求实现一个基本的计算器,用于计算包含加、减、乘、除以及括号的字符串表达式的值。这是一个典型的解析和计算问题,可以通过栈(Stack)数据结构来解决。栈用于存储操作数和操作符,以便按照正确的运算顺序进行计算。

解题步骤如下:

  1. 解析表达式:遍历字符串,识别数字和操作符,将数字转换为整数并存储,遇到操作符时,根据优先级进行处理。

  2. 处理操作符:对于加(+)和减(-),直接从栈中弹出两个操作数进行计算后将结果压入栈。对于乘(*)和除(/),由于它们具有更高的优先级,需要先计算它们。除法的结果需要向下取整。

  3. 处理括号:遇到左括号((),将当前计算的结果压入栈,并开始新的计算;遇到右括号()),将括号内的表达式计算完毕后,再与之前的计算结果进行合并。

  4. 计算结果:遍历结束后,栈中剩余的元素即为最终结果。

在实现过程中,我们需要注意以下几点:

  • 操作符的优先级:乘除优先于加减,括号内的表达式优先于括号外的表达式。
  • 操作符的结合性:加减和乘除都是左结合的,即从左到右计算。
  • 除法的整数结果:除法运算应只保留整数结果,不进行四舍五入。

通过以上步骤,我们可以构建一个简单的计算器来解析和计算字符串表达式的值。这种方法不仅适用于本题,也可以扩展到更复杂的表达式解析和计算中。

在编写代码时,我们使用了两个栈,一个用于存储操作数,另一个用于存储操作符。通过遍历输入的表达式,我们依次处理数字和操作符,根据操作符的优先级和结合性来决定何时进行计算。最终,当遍历完整个表达式后,栈中剩余的元素即为计算结果。

这种方法的优点是逻辑清晰,易于实现,且能够正确处理包含括号的复杂表达式。缺点是对于非常长的表达式,可能会有较大的空间开销,因为需要存储整个表达式的操作数和操作符。但在大多数情况下,这种方法是解决此类问题的高效方式。

以下附上ACM模式下的cpp代码

#include <iostream>
#include <stack>
#include <string>
#include <cctype>

int precedence(char op) {
    if (op == '+' || op == '-') return 1;
    if (op == '*' || op == '/') return 2;
    return 0;
}

int applyOp(int a, int b, char op) {
    switch (op) {
        case '+': return a + b;
        case '-': return a - b;
        case '*': return a * b;
        case '/': return a / b; // 注意:这里直接除以b,不进行四舍五入
    }
    return 0;
}

int calculate(std::string expression) {
    std::stack<int> values;
    std::stack<char> ops;
    int i = 0;
    while (i < expression.length()) {
        if (expression[i] == ' ') {
            ++i;
            continue;
        }
        if (expression[i] == '(') {
            ops.push(expression[i]);
            ++i;
        } else if (expression[i] == ')') {
            while (!ops.empty() && ops.top() != '(') {
                int val2 = values.top();
                values.pop();
                int val1 = values.top();
                values.pop();
                char op = ops.top();
                ops.pop();
                values.push(applyOp(val1, val2, op));
            }
            if (!ops.empty()) ops.pop();
            ++i;
        } else if (isdigit(expression[i])) {
            int val = 0;
            while (i < expression.length() && isdigit(expression[i])) {
                val = (val * 10) + (expression[i] - '0');
                ++i;
            }
            values.push(val);
            --i;
        } else {
            while (!ops.empty() && precedence(ops.top()) >= precedence(expression[i])) {
                int val2 = values.top();
                values.pop();
                int val1 = values.top();
                values.pop();
                char op = ops.top();
                ops.pop();
                values.push(applyOp(val1, val2, op));
            }
            ops.push(expression[i]);
            ++i;
        }
    }
    while (!ops.empty()) {
        int val2 = values.top();
        values.pop();
        int val1 = values.top();
        values.pop();
        char op = ops.top();
        ops.pop();
        values.push(applyOp(val1, val2, op));
    }
    return values.top();
}

int main() {
    std::string expression;
    std::cout << "Enter an expression: ";
    std::cin >> expression;
    std::cout << "The result is: " << calculate(expression) << std::endl;
    return 0;
}