52.简单四则运算解析器|Marscode AI刷题

6 阅读3分钟

1.题目

问题描述

小F面临一个编程挑战:实现一个基本的计算器来计算简单的字符串表达式的值。该字符串表达式有效,并可能包含数字(0-9)、运算符+-及括号()。注意,字符串中不包含空格。除法运算应只保留整数结果。请实现一个解析器计算这些表达式的值,且不使用任何内置的eval函数。


测试样例

样例1:

输入:expression = "1+1"

输出:2

样例2:

输入:expression = "3+4*5/(3+2)"

输出:7

样例3:

输入:expression = "4+2*5-2/1"

输出:12

样例4:

输入:expression = "(1+(4+5+2)-3)+(6+8)"

输出:23

样例5:

输入:expression = "2*(5+52)/3+(6+83)"

输出:40

2.思路

  1. 初始化两个栈:一个用于存储操作数(数字),另一个用于存储运算符。

  2. 遍历表达式中的每个字符

    • 如果当前字符是数字,则解析完整的数字并压入操作数栈。

    • 如果当前字符是左括号(,则直接压入运算符栈。

    • 如果当前字符是右括号),则从运算符栈中弹出运算符,并从操作数栈中弹出两个操作数进行计算,直到遇到左括号(

    • 如果当前字符是运算符(+-*/),则比较当前运算符与运算符栈顶运算符的优先级:

      • 如果当前运算符优先级低于或等于栈顶运算符,则先计算栈顶运算符,并将结果压入操作数栈,然后将当前运算符压入运算符栈。
      • 否则,直接将当前运算符压入运算符栈。
  3. 处理完表达式后,如果运算符栈中还有运算符,则依次弹出运算符并进行计算,直到运算符栈为空。

  4. 最终结果即为操作数栈中的唯一元素。

3.代码

#include <iostream>
#include <string>
#include <stack>
#include <cctype>
using namespace std;

//确定优先级
int precedence(char op) {
    if (op == '+' || op == '-') {
        return 1;
    }else 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;
    }
    return 0;
}

int solution(const string& tokens) {
    stack<int> values; //存放操作数
    stack<char> ops; //存放运算符
    for (size_t i = 0; i < tokens.length(); ++i) {
        // 跳过空格
        if (isspace(tokens[i])) {
            continue;
        }
        // 当前字符是数字,则解析完整的数字
        if (isdigit(tokens[i])) {
            int val = 0;
            while (i < tokens.length() && isdigit(tokens[i])) {
                val = (val * 10) + (tokens[i] - '0');
                ++ i;
            }
            --i; //补偿最后多加一次的递增
            values.push(val);
        }
        // 当前字符是左括号,直接压入运算符栈 
        else if (tokens[i] == '(') {
            ops.push(tokens[i]);
        }
        // 当前字符是右括号,处理栈中的运算符直到遇到左括号  
        else if (tokens[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();
            }
        }
        // 当前字符是运算符  
        else {
            while (!ops.empty() && precedence(ops.top()) >= precedence(tokens[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(tokens[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() {
    // You can add more test cases here
    std::cout << (solution("1+1") == 2) << std::endl;
    std::cout << (solution("3+4*5/(3+2)") == 7) << std::endl;
    std::cout << (solution("4+2*5-2/1") == 12) << std::endl;
    std::cout << (solution("(1+(4+5+2)-3)+(6+8)") == 23) << std::endl;
    return 0;
}

4.参考资料

字节青训-简单四则运算解析器-CSDN博客