表达式求值(栈)

                          表达式求值

时间限制: 3000 ms  |  内存限制: 65535 KB
难度: 4
描述
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
这个使用到了栈:

首先定义了两个栈点,一个是放字符的栈点,一个是放数据的栈点。

并且在每一个放字符的栈点都在其首端放上了个“(”左括号,在末端放上一个“)”右括号。

代码中只有一个for循环,每次执行一次,要记住,字符串是从第二个开始读取的,记录字符串的长度也是s1之后的长度。

讲解下代码的运行过程吧:

看例子(((1+2)*5+1)/4)

第一次循环读取的是(,那么就把(压栈到字符栈里面

第二次循环读取的是(,就把(压栈到字符栈里

第三次循环读取的还是(,继续吧(压栈到字符栈里

第四次循环读取到了数字1,进行判断是不是小数,判断后(稍后讲解如何判断小数部分)不是小数,就把数字1压栈到数字栈里面。

第五次循环,读取到了字符+,进入while()中,因为不满足while循环的条件,因为此时的栈里面只有(((,这时再把字符+压栈到字符栈里面;

第六次循环,读取到了数字2,判断后把2压栈到了数据栈里面;

第七次循环,读取到了字符),满足while循环里的条件因为此时字符栈里面放的是(((+,满足while条件后,取数据栈栈顶元素2赋值给a,然后删除栈顶元素,

然后继续取数据栈栈顶元素1赋值给b,然后删除栈顶元素,进入swith()分支语句中,switch语句里面取字符栈顶元素,我们取到了字符+,c=a+b,得到3,

然后把3存到数据栈中,也就是把3压栈到数据栈中后,删除字符栈,就是删除我们运算过的字符+,然后再删除字符栈栈顶元素,也就是删除字符(,此时的字符栈里面是((;接着进行下一轮的循环

第八次循环,读取的是字符*,然后把字符*压栈到字符栈里面,

第九次循环,读取到数字5,判断后,把5压栈到数据栈中

第十次循环,读取到了字符+,满足while循环后根据里面的流程走,把数据栈里的数据取出后删除栈顶元素把计算结果15压栈到数据栈中把字符栈栈顶元素*删除,最后再把字符+压栈到字符栈中

第十一次循环读取到数字1,判断后压栈到数据栈此时的数据站里面有15和1,

第十二次循环读取到了),满足while条件,再次进行取栈顶元素删除栈顶元素的操作,

把计算结果16放进数据栈里之后删除字符栈中运算过的字符+,再次删除栈顶元素),此时的字符栈里面只有一个”(“

第十三次循环读取到了字符/,把字符/压栈到字符栈里面,字符栈里面此时有(/

第十四次循环读取数字4,判断后放入数据栈中

第十五次循环读取到字符),满足while条件进行取栈顶元素删除栈顶元素,将计算结果4放入数据栈中后,删除运算过的字符/,最后再删除栈顶元素(,此时循环结束,输出数据栈中栈顶元素。此时字符栈为空,数据栈也只有一个元素。

这就是整个程序过程,别只是看看,看着解析动手画画,画两个数组。根据程序步骤放元素取元素删除元素。

关于判断小数点的那一部分是,b记录下来的是小数点的位置,

例如1.000读入进去后,记得小数点位置是b=1,v=1000之后i++往后走加到了i=5的时候不是数字和小数点了,退出while循环,i--,i=4,那么i-b=(4-1)=3,说明小数点后面有3位数,

b!=0,说明是小数,v/10*3就是小数1.000了,动手试试。


#include
#include
#include
#include
using namespace std;
char s[1010];
stack shuju;
stack zifu;
int main()
{
int T,i,len;
scanf("%d",&T);
while(T--)
{
scanf("%s",&s[1]);
len=strlen(&s[1]);
s[0]='(';
s[len]=')';
for(i=0;i<=len;i++)
{
if(s[i]=='(') 
{
zifu.push(s[i]);
}
else if(s[i]>='0'&&s[i]<='9')
{
double v=0;
int b=0;
while(s[i]>='0'&&s[i]<='9'||s[i]=='.')
{
if(s[i]=='.')
b=i;
else
v=v*10+(s[i]-'0');
i++;
}
i--;
if(b!=0)
{
shuju.push(v/pow(10,i-b));
}
else
shuju.push(v);
}
else if(s[i]=='+'||s[i]=='-')
{
while(zifu.top()!='(')
{
double a=shuju.top();shuju.pop();
double b=shuju.top();shuju.pop();
double c;
switch(zifu.top())
{
case '+':c=a+b;break;
case '-':c=b-a;break;
case '*':c=a*b;break;
case '/':c=b/a;break;
}
shuju.push(c);
zifu.pop();
} 
zifu.push(s[i]);
}
else if(s[i]=='*'||s[i]=='/')
{
if(zifu.top()=='*')
{
double a=shuju.top();shuju.pop();
double b=shuju.top();shuju.pop();
           shuju.push(a*b);
zifu.pop();
} 

   else if(zifu.top()=='/')
{
double a=shuju.top();shuju.pop();
double b=shuju.top();shuju.pop();
           shuju.push(b/a);
zifu.pop();
} 
zifu.push(s[i]);
} 
else if(s[i]==')')
{
while(zifu.top()!='(')
{
double a=shuju.top();shuju.pop();
double b=shuju.top();shuju.pop();
double c;
switch(zifu.top())
{
case '+':c=a+b;break;
case '-':c=b-a;break;
case '*':c=a*b;break;
case '/':c=b/a;break;
}
shuju.push(c);
zifu.pop();
} 
zifu.pop();
}
}
printf("%.2lf\n",shuju.top());
shuju.pop();
}
return 0;
}


压栈,取栈顶元素,和删除栈顶元素是name.push(),name.top(),mane.pop()



你可能感兴趣的:(醍醐灌顶,数论,NYOJ)