抓住核心要点:遇到优先级比自己大的运算符就停止弹栈,否则小于等于的运算符都要一直弹,知道栈为空再把当前的运算符push进去
#include <iostream>
#include <cstdio>
#include <stack>
#include <cstring>
using namespace std;
int main(void) {
char s[205]; //s存输入的中缀表达式
while(gets(s) != NULL && !(strlen(s) == 1 && s[0] == '0')) {
string haha = ""; //用来写后缀表达式
stack <char> pt; //用来存操作符,通过优先级调整后缀表达式顺序,也可以用完全二叉树存,但麻烦
int len = strlen(s); //不要偷懒不写len,如果每次都strlen有时就超时
for (int i = 0; i < len; i++) {
if (s[i] == '+' || s[i] == '-') { //因为+和-优先级一样,所以遇不到比它两小的运算符,栈就要全部弹到后缀表达式中
while(!pt.empty()) {
haha += pt.top();
pt.pop();
}
pt.push(s[i]);
}
else if (s[i] <= '9' && s[i] >= '0') {
haha += s[i];
}
else if (s[i] == '*' || s[i] == '/') {
if (!pt.empty() && (pt.top() != '+' && pt.top() != '-') ) {
while(!pt.empty() && (pt.top() != '+' && pt.top() != '-')) { //只要栈顶不是比它高的,等于和小于的优先级运算符都要弹到后缀表达式中
haha += pt.top();
pt.pop();
}
}
pt.push(s[i]);
}
else { //空格添加到后缀表达式中
haha += s[i];
}
}
while(!pt.empty()) { //目前存的运算符全部弹到后缀表达式中
haha += pt.top();
pt.pop();
}
stack <double> number; //存运算值
int l = haha.length();
for (int i = 0; i < l; i++) {
if (haha[i] <= '9' && haha[i] >= '0') { //字符转数字
double sum = 0;
while(i < l && haha[i] <= '9' && haha[i] >= '0') {
sum = (sum*10 + haha[i]-'0')*1.00;
i++;
}
number.push(sum);
i--;
}
else if (haha[i] != ' ') { //遍历的时候遇到一个运算符就将number的栈顶元素和弹出后的栈顶元素进行操作运算
double a = number.top();
number.pop();
double b = number.top();
if (haha[i] == '+') {
number.top() = a + b;
}
else if (haha[i] == '-') {
number.top() = b - a;
}
else if (haha[i] == '*') {
number.top() = b * a;
}
else if (haha[i] == '/') {
number.top() = b / a;
}
}
}
printf("%.2lf\n", number.top());
}
return 0;
}