题目描述
读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。
输入
测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。
输出
对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。
思路解析
先用getline函数输入一行表达式,将表达式进行解析。解析时需要用到两个栈,栈A存储运算数据,栈B用来存储运算符。从前往后逐个扫描表达式中的字符,当扫描到数字时,将数字(可能有多位)入栈A,当扫描到运算符时,需要判断一下当前运算符op优先级是否比栈B顶的优先级高,如果当前运算符优先级高,则入栈B,否则将栈B顶的运算符和栈A顶端的两个运算数据取出,进行运算,并将结果如栈A,直到当前运算符op优先级比栈顶优先级高为止,将op如栈B。扫描完后,按次序取出栈B中的一个的运算符,栈A中的两个运算数,进行计算,将结果入栈A,直到栈B中无运算符,栈A中只有一个结果C,C即为表达式结果。
代码
#include <iostream>
#include <string>
#include <stack>
using namespace std;
int lever(char op){
if(op=='+' || op=='-'){
return 1;
}else{
return 2;
}
}
double func(double a,double b,char op){
if(op=='+'){
return a+b;
}else if(op=='-'){
return a-b;
}else if(op=='*'){
return a*b;
}else{
return a/b;
}
}
void cal(string exp){
stack<double> num;//存数字
stack<char> oper;//存运算符
int len = exp.length(),index_n=0,index_o=0,number=0,lev=0;
double a,b;
char t;
for(int i=0;i<len;i++){
if(exp[i]>='0' && exp[i]<='9'){
number = number*10 + exp[i]-'0';
}else if(exp[i]!=' '){
num.push(number);
number=0;
//运算符比栈顶等级高则入栈,否则进行一次运算
if(lev<lever(exp[i])){
oper.push(exp[i]);
lev = lever(exp[i]);
continue;
}
while(lev>=lever(exp[i])){
t = oper.top();
oper.pop();
a = num.top();
num.pop();
b = num.top();
num.pop();
num.push(func(b,a,t));
if(oper.empty()){
break;
}
lev = lever(oper.top());
}
oper.push(exp[i]);
lev = lever(exp[i]);
}
}
num.push(number);//将最后一个数字入栈
while(!oper.empty()) {
t = oper.top();
oper.pop();
a = num.top();
num.pop();
b = num.top();
num.pop();
num.push(func(b,a,t));
}
printf("%.2f\n",num.top());
}
int main(){
string exp;
while(1){
getline(cin,exp);
if(exp=="0"){
break;
}
cal(exp);
}
return 0;
}