HJ50 四则运算 CPP版本

48 阅读1分钟

不简单啊。。。

描述

中缀表达式求值

解析

参考可乐大数据-csdn

#include <iostream>
#include <string>
#include <stack>
#include <unordered_map>
using namespace std;
unordered_map<char, char> mp = {{'(', ')'}, {'[', ']'}, {'{', '}'}};
int getans(string str) {
    int length = str.size();
    stack<int> st;
    int number = 0;
    char opr = '+';
    int i = 0;
    int now;
    while (i < length) {
        char ch = str[i];
        if (mp.count(ch)) {
            char target = mp[ch];
            ++i;
            int begin = i;
            int cnt = 1;
            while (i < length) {
                if (str[i] == target) {
                    if (--cnt == 0) break;
                } else if (str[i] == ch) ++cnt;
                ++i;
            }
            number = getans(str.substr(begin, i - begin));
        } else if (isdigit(ch)) {
            number = number * 10 + ch - '0';
        } else {
            
            switch (opr) {
                case '+':
                    st.push(number);
                    break;
                case '-':
                    st.push(-1 * number);
                    break;
                case '*':
                    now = st.top();
                    st.pop();
                    st.push(now * number);
                    break;
                case '/':
                    now = st.top();
                    st.pop();
                    st.push(now / number);
                    break;
            }
            opr = ch;
            number = 0;
        }
        ++i;
    }
    switch (opr) {
        case '+':
            st.push(number);
            break;
        case '-':
            st.push(-1 * number);
            break;
        case '*':
            now = st.top();
            st.pop();
            st.push(now * number);
            break;
        case '/':
            now = st.top();
            st.pop();
            st.push(now / number);
            break;
    }
    int ans = 0;
    while (!st.empty()) {
        ans += st.top();
        st.pop();
    }
    return ans;
}
int main() {
    string str;
    cin >> str;
    cout << getans(str);
    return 0;
}

整体思路

unordered_map<char, char> mp = {{'(', ')'}, {'[', ']'}, {'{', '}'}};
int getans(string str) {
    int length = str.size();
    stack<int> st;
    int number = 0;
    char opr = '+';    // 前一个符号
    int i = 0;
    while (i < length) {
        char ch = str[i];
        if (mp.count(ch)) {
            // 细节1:括号内递归
        } else if (isdigit(ch)) {
            number = number * 10 + ch - '0';
        } else {
            // 细节2:运算符计算并更新
        }
        ++i;
    }
    // 细节3: 最后一个运算符计算
    
    // stack所有元素求和
}

细节1 括号递归

注意多个括号嵌套的情况(1+(1+2)*3),不能是匹配到反括号)就结束,那样就会出现1+(1+2)导致逻辑错误。
需要一个cnt计数,遇到第一个括号ch相同则++,遇到与第一个括号匹配的反括号则--,cnt为0则匹配完成。

char target = mp[ch];
++i;
int begin = i;
int cnt = 1;
while (i < length) {
    if (str[i] == target) {
        if (--cnt == 0) break;
    } else if (str[i] == ch) ++cnt;
    ++i;
}
number = getans(str.substr(begin, i - begin));

细节2&&细节3 运算符计算并更新

opr实际是上一个符号,默认为'+'。

上一个符号:表达式(1*1)可被理解为+1*1,类似的-1*2通过这种转换,即栈里边为 0,-1实现了负数的判别。

因此,循环结束还有最后一个符号没处理,需要在循环之外处理,这就是细节3