题目描述
Problem Description
读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。
Input
测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。
Output
对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。
Sample Input
1 + 2 4 + 2 * 5 - 7 / 11 0
Sample Output
3.00 13.36
解题思路: 此题是典型的栈的例题,运用到了用栈来实现中缀表达式转化成后缀表达式及其求解的方法,
中缀表达式转化成后缀表达式的方法:
1.遇到操作数:直接输出(添加到后缀表达式中) 2.栈为空时,遇到运算符,直接入栈 3.遇到左括号:将其入栈 4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。 5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈 6.最终将栈中的元素依次出栈,输出。
后缀表达式的计算: 从左到右扫描后缀表 达式,遇到运算符就把表达式中该运算符前面两个操作数取出并运算,然后把结果带回后缀表达式;继续扫描直到后缀表达式最后一个表达式。
本题还需注意空格的入栈
代码如下:#include<stdio.h> #include<string.h> #include<stack> #include<algorithm> using namespace std; char s[300],suffix[1000]; int fuhao(char ch)//各个符号的优先级 { switch(ch) { case '#':return 0; case '+':return 1; case '-':return 1; case '*':return 2; case '/':return 2; } return -1; } int is_num(char ch)//是不是数字 { if(ch>='0'&&ch<='9') return 1; return 0; } void Transform(char *suffix,char *s)//转换成后缀式 { stack<char>op; int l=strlen(s),i,k=0; op.push('#'); for(i=0;i<l;i++) { if(is_num(s[i])||s[i]==' ') //数字或空格 存入数组 suffix[k++]=s[i]; else { while(!op.empty()&&fuhao(op.top())>=fuhao(s[i]))//将stack中的所有的优先级不小于当前操作符的优先级的操作符发送给后缀式 { suffix[k++]=op.top(); //栈顶取出放入数组 op.pop(); //出栈 } if(s[i]!='#') op.push(s[i]); } } suffix[k]='\0'; } void Calculate() { stack<double>ans; int i=0,l=strlen(suffix); while(i<l) { if(suffix[i]==' ') { i++;continue; } if(suffix[i]=='#') break; else { double a=0; int flag=0; while(is_num(suffix[i])) //是否为数字 { a*=10; a+=(suffix[i++]-'0'); flag=1; } if(flag) ans.push(a); if(suffix[i]==' ') {i++;continue;}//不要写成if(suffix[i++]=' ') if(fuhao(suffix[i])>0) { double num1,num2,num3; num1=ans.top(); ans.pop();//注意弹出。 num2=ans.top(); ans.pop(); switch(suffix[i++]) { case '+':num3=num2+num1;break; case '-':num3=num2-num1;break; case '*':num3=num2*num1;break; case '/':num3=num2/num1;break; } ans.push(num3); } } } printf("%.2lf\n",ans.top()); } int main() { while(gets(s))//注意用gets,因为有空格,不要用scanf { memset(suffix,NULL,sizeof(suffix)); int l=strlen(s); if(l==1&&s[0]=='0') break; else { s[l]='#';//加个#,作为结束标志 Transform(suffix,s); Calculate(); } } return 0; }