题目描述:
读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。
输入:
测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。
没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。
输出:
对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。
代码实现:
#include <stack>
#include <string>
#include <cstdio>
#include <map> //管理优先级
using namespace std;
/*
* 运算符栈 新来的运算符优先级更高则压栈 优先级更低则弹栈
* 中间结果也要用一个栈
* 从左往右遍历表达式
* 1、数字 num压栈
* 2、 运算符 a, 更高优先级 oper压栈
* b, 更低优先级 先oper弹出一个运算符 再弹出两个 再运算 ;运算结果压回num
*/
int main(){
char buf[300];
map<char,int> priority = {
{'$',0},
{'+',1},{'-',1},
{'*',2},{'/',2}
};
while(fgets(buf,300,stdin) != NULL){
string expr = buf;
expr.pop_back(); //末尾多了一个换行弹掉
if(expr == "0"){
break; // 0 则结束执行
}
expr.push_back('$');//补充一个虚拟的终止符
string num;//做一个 拼接的操作 ;用来收集单独的0-9 以组成一个数字 1 2 3 4 --> 1234
stack<double> numstack; //中间数据 栈
stack<char> operstack; //操作符 栈
for(unsigned i = 0;i<expr.size();i++){ //从左往右遍历
if(expr[i] >= '0' && expr[i] <= '9'){ //收集数字
num.push_back(expr[i]); //连接操作
} else if(expr[i] == ' '){ //当前读的数字 如果是空格
if (num != ""){ //num不为空的情况
numstack.push(stod(num));
//把刚才收集的数字num变成double类型,stod ,收集的1234 变成浮点类型的1234
//压到数字栈里面
num = ""; // 让num等于一个空的,这个数据收集完了,下一个数据从新再开始
}
} else{
// + - * / $
if(expr[i] == '$'){
if(num != ""){ //先把前面收集的字符串 放好
numstack.push(stod(num));
num = "";
}
}
//操作符栈非空 并且 当遇到运算符 新来的运算符比旧的运算符优先级更高 则压栈 ,否则 更低 做弹栈操作
while(!operstack.empty() && priority[operstack.top()] >= priority[expr[i]]){
//新来的运算符的优先级不高于栈顶的优先级
char oper = operstack.top(); //拿出原来的运算符
operstack.pop(); //弹出栈顶运算符
double rhs = numstack.top(); //弹出右手边的数据
numstack.pop();
double lhs = numstack.top(); //弹出右手边的数据
numstack.pop();
switch (oper) { //判断oper运算符 有哪几种情况
case '+':
numstack.push(lhs + rhs);
break;
case '-':
numstack.push(lhs - rhs);
break;
case '*':
numstack.push(lhs * rhs);
break;
case '/':
numstack.push(lhs / rhs);
break;
}
}
//新来的 expr[i]优先级更低 都计算了
operstack.push(expr[i]); //新来的优先级更高 压栈
}
}
printf("%.2lf\n",numstack.top()); //所有的数算完栈只剩一个数字了
}
}
输入
1 + 2
4 + 2 * 5 - 7 / 11
0
输出
3.00
13.36