ACM队的mdd想做一个计算器,但是,他要做的不仅仅是一计算一个A+B的计算器,他想实现随便输入一个表达式都能求出它的值的计算器,现在请你帮助他来实现这个计算器吧。
比如输入:“1+2/4=”,程序就输出1.50(结果保留两位小数)
第一行输入一个整数n,共有n组测试数据(n<10)。 每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个运算式,每个运算式都是以“=”结束。这个表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。数据保证输入的操作数中不会出现负数。 数据保证除数不会为0
每组都输出该组运算式的运算结果,输出结果保留两位小数。
复制
2 1.000+2/4= ((1+2)*5+1)/4=
1.50 4.00
解题代码:
#include
#include
#include
#include
#include
#include
using namespace std;
stack s1; //符号栈
stack n1; //数字栈
bool first1(char s1,char s2){ //判断两个符号的优先级,若s1优先返回 true 否则返回false
int t1,t2;
if(s1=='+')t1=1;if(s1=='-')t1=1;if(s1=='*')t1=2;if(s1=='/')t1=2;
if(s2=='+')t2=1;if(s2=='-')t2=1;if(s2=='*')t2=2;if(s2=='/')t2=2;
return t1>=t2;
}
void mathnum(){ //此函数为运算操作,包括从数字栈取数,从符号栈取符号,并去栈顶,将运算结果加入到数字栈顶;
double num1=n1.top();n1.pop();
if(s1.top()=='+')num1=n1.top()+num1;
if(s1.top()=='-')num1=n1.top()-num1;
if(s1.top()=='*')num1=n1.top()*num1;
if(s1.top()=='/')num1=n1.top()/num1;
s1.pop();n1.pop();n1.push(num1);
}
int main()
{
int t;
cin>>t;
while(t--){
char ss[1000];
double num1=0,bj=0;//bj是用来标记数字是处于整数位还是小数位
cin>>ss;
for(int i=0;i='0'&&ss[i]<='9'&&bj==0)num1=num1*10+(ss[i]-'0'); //首先应该区分的是数字和字符,若为数字则一直乘到不是数字为止
else if(ss[i]>='0'&&ss[i]<='9'&&bj!=0){
bj=bj*0.1;
num1+=bj*(ss[i]-'0');
}
else{
if(ss[i]=='.'){bj=1;continue;}
if(ss[i-1]>='0'&&ss[i-1]<='9'){n1.push(num1);num1=0;bj=0;} //若不是数字,则判断上一位是不是数字若是数字,则将num1加入到n1数字栈中
if(ss[i]=='='){
while(!s1.empty())mathnum();
printf("%.2f\n",n1.top()); //输出结果
n1.pop(); //因为有t个测试组,所以要将n1数字栈清空
break;
}
if(ss[i]=='('||s1.empty()||s1.top()=='(')s1.push(ss[i]); //若此位是字符,则有三种情况是必须直接将字符加入到字符栈中 ,分别是:左括号,左括号后的第一个运算符,整个算数表达式的第一个运算字符
else if(ss[i]==')'){ //若为右括号,则将括号内的所有运算符运算完毕
while(s1.top()!='('){
mathnum();
}
s1.pop(); //将左括号清除
}else { //剩下的情况肯定是当前符号和符号栈栈顶符号都是运算符,则根据优先级进行相应运算
while(first1(s1.top(),ss[i])){ //若符号栈栈顶符号优先级高,则先将栈顶进行运算
mathnum();
if(s1.empty()||s1.top()=='(')break; //若此时符号栈已空或者栈顶已经为左括号,则跳出循环
}
s1.push(ss[i]); //此时,比当前优先级高的符号都已运算完毕,将当前符号加入到符号栈中
}
}
}
}
return 0;
}