HJ50 四则运算
题目描述
数据范围:表达式计算结果和过程中满足 |val| \le 1000 \∣val∣≤1000 ,字符串长度满足 1 \le n \le 1000 \1≤n≤1000 。
输入描述:
输入一个算术表达式,如
输出描述:
得到计算结果
示例:
输入: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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix