HJ50 四则运算

题目描述

输入一个表达式(用字符串表示),求这个表达式的值。
保证字符串中的有效字符包括[‘0’-‘9’],‘+’,‘-’, ‘*’,‘/’ ,‘(’, ‘)’,‘[’, ‘]’,‘{’ ,‘}’。且表达式一定合法。

数据范围:表达式计算结果和过程中满足 |val| \le 1000 \val1000  ,字符串长度满足 1 \le n \le 1000 \1n1000 。

输入描述:

输入一个算术表达式,如

输出描述:

得到计算结果

示例:

输入:3+2*{1+2*[-4/(8-6)+7]}
输出:25

 

 解题思路:

双栈法。利用两个栈,一个存储待计数的数值,一个存储运算符。输入的算术表达式里有三点需要注意:1.存在多种括号;2.待计算的数值有使用正负符号表示;3.数值最多能占3个字符,要考虑串转数字。

思路是先处理出现括号的情况,再考虑数值的情况,最后考虑运算符(因为数值一定会先出现在运算符前,然后交替出现;括号是优先级最高的符号,一旦出现需要优先处理)。

括号优先级最高,而'*'和'/'的优先级要较'+'和'-'更高。栈外符号优先级低,则带计算数值出栈计算;栈外符号优先级高,则入栈保存符号。

我们将得到的待计算数值和运算符分别压入栈中,解题的关键在出栈计算的时机。

当遇到开括号时,我们只需无脑压入栈中即可。表达式里出现三种括号,但是同一类括号,它的闭括号一定是会先遇到自己对应的开括号,然后相互抵消掉,所以无论有多少种括号,我们都可以只当作一种来处理。

遇到闭括号时,根据常识,我们需要将括号里的表达式计算完。所以遇到闭括号时,我们需要不断取出栈中保存的运算符和数值进行计数,直到遇到开括号抵消。

然后,我们需要考虑表达式中遇到数字的情况,需要把字符串转化为数字,可以使用stoi函数,也可以使用atoi(tmp.c_str())。我们需要考虑第一个字符可能是表示正负的意思。

在将数值压入栈中后,下一个遇到的不是括号就必然是运算符。我们需要将遇到的运算符都压入栈中保存,在遇到括号时在取出计算。

因为表达式可能存在括号,也可能不存在,所以我们在输入的原始表达式前加上'(',在表达式尾部加上')'。这样我们就只需要考虑一种情况了。

代码如下:

复制代码
#include <iostream>
#include <string>
#include <stack>

using namespace std;

void calc(stack<int>& stackValue, stack<char>& stackOper) {
    int res = 0;
    int y = stackValue.top();
    stackValue.pop();
    int x = stackValue.top();
    stackValue.pop();
    char op = stackOper.top();
    stackOper.pop();

    switch (op) {
    case '+':
        res = x + y;
        break;
    case '-':
        res = x - y;
        break;
    case '*':
        res = x * y;
        break;
    case '/':
        res = x / y;
        break;
    default:
        res = 0;
        break;
    }
    stackValue.push(res);
}

bool isPriority(char op1, char op2) {
    if (op1 == '(')
        return false;
    else if ((op1 == '+' || op1 == '-') && (op2 == '*' || op2 == '/'))
        return false;
    return true;
}

int main() {
    string reg;
    bool flag = false;
    while ( cin>>reg ) {
        stack<int> stackValue;
        stack<char> stackOper;
        stackOper.push('(');
        reg += ')';
        for (int i = 0; i < reg.length(); i++) {
            if (reg[i] == '(' || reg[i] == '[' || reg[i] == '{')
                stackOper.push('(');
            else if (reg[i] == ')' || reg[i] == ']' || reg[i] == '}') {
                while (stackOper.top() != '(') {
                    calc(stackValue, stackOper);
                }
                stackOper.pop();
            }
            else if (flag) {
                while(isPriority(stackOper.top(), reg[i])) {
                    calc(stackValue, stackOper);
                }
                stackOper.push(reg[i]);
                flag = false;
            }
            else {
                int j = i;
                if (reg[j] == '-' || reg[j] == '+')
                    i++;
                while (reg[i] - '0' >= 0 && reg[i] - '0' <= 9) {
                    i++;
                }
                string temp = reg.substr(j, i - j);
                stackValue.push(atoi(temp.c_str()));
                i--;
                cout << "temp: " << temp << endl;
                flag = true;
            }
        }
        cout << stackValue.top() << endl;
    }
    return 0;
}
复制代码

 

posted @   An2i  阅读(116)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示