第九届河南省程序设计大赛
A 表达式求值
内存限制:64MB 时间限制:1s Special Judge: No
题目描述:
假设表达式定义为: 1. 一个十进制的正整数 X 是一个表达式。 2. 如果 X 和 Y 是 表达式,则 X+Y, X*Y 也是表达式; *优先级高于+. 3. 如果 X 和 Y 是 表达式,则 函数 Smax(X,Y)也是表达式,其值为:先分别求出 X ,Y 值的各位数字之和,再从中选最大数。 4.如果 X 是 表达式,则 (X)也是表达式。 例如: 表达式 12*(2+3)+Smax(333,220+280) 的值为 69。 请你编程,对给定的表达式,输出其值。
输入描述:
【标准输入】 第一行: T 表示要计算的表达式个数 (1≤ T ≤ 10) 接下来有 T 行, 每行是一个字符串,表示待求的表达式,长度<=1000
输出描述:
【标准输出】 对于每个表达式,输出一行,表示对应表达式的值。
样例输入:
复制
3 12+2*3 12*(2+3) 12*(2+3)+Smax(333,220+280)
样例输出:
18 60 69
这道题是我的心病啊,之前看到别人写的关于这道题的题解都是说要用到中缀转后缀(逆波兰式)
因为我对逆波兰式不太熟悉所以想着还是按照中缀来写,遇到Smax函数时直接跳过,通过函数中的逗号来判断是不是这个函数
想法是对的,样例也是对的,但就是算不对,老是出现运行时错误,但又想不出来反例,
终于今天让我注意到了,我建的两个用来存放运算符的栈出了问题,尤其是用来储存运算结果的是sta1,因为有的时候可能需要连续抛出两个数进行对应的运算,但是此时sta1可能只有一个数,所以就会出现运行时错误,
妈呀,如果不改过来我可能以后就对表达时产生抵触了
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<cmath>
using namespace std;
int a1[8][8]={
{0,0,0,0,0,0,0,0},
{0,1,0,1,0,1,1,0},
{0,1,1,1,0,1,1,1},
{0,0,0,1,0,1,0,0},
{0,0,0,0,1,1,0,0},
{0,1,1,1,1,1,1,1},
{0,1,0,1,0,1,1,0},
{0,1,1,1,0,1,1,1},
};
int sw(int x,int y)//求两个多位数数为相加的结果,并返回较大的值
{
int n1=0,n2=0;
while(x!=0)
{
n1+=x%10;
x/=10;
}
while(y!=0)
{
n2+=y%10;
y/=10;
}
n1=n1>n2?n1:n2;
return n1;
}
int bj(char a,char b)//判断算符优先顺序
{
int i=0,j=0;
if(a=='+')i=1;if(a=='*')i=2;if(a==',')i=3;if(a=='(')i=4;if(a==')')i=5;if(a=='-')i=6;if(a=='/')i=7;
if(b=='+')j=1;if(b=='*')j=2;if(b==',')j=3;if(b=='(')j=4;if(b==')')j=5;if(b=='-')j=6;if(b=='/')j=7;
return a1[i][j];
}
int main()
{
int k;
stack<int>sta1;
stack<char>sta2;
char str1[1090];
cin>>k;
sta2.push('#');
sta1.push(-99999999);
while(k--)
{
cin>>str1;
int len1=strlen(str1);
int n1=0;
for(int i=0;i<len1;i++){
if(str1[i]<='9'&&str1[i]>='0')//添加数字时,可能是一个多位数,所以要
{
int n2=str1[i]-'0';
i++;
while(str1[i]>='0'&&str1[i]<='9'&&i<len1)
{
n2=n2*10+str1[i]-'0';
i++;
}
sta1.push(n2);
if(i>=len1)
break;
}
if((str1[i]<'0'||str1[i]>'9')&&sta2.top()=='#')//添加第一个算符
sta2.push(str1[i]);
else if(str1[i]=='(')//若是(,则直接插入栈
{
sta2.push(str1[i]);
continue;
}
else if(str1[i]=='S')//若是Smax,则直接跳过,使用,来表示
{
i=i+3;
continue;
}
else if(bj(sta2.top(),str1[i])&&sta2.top()!='#'){//若栈顶算符优先,则进行相对应操作
int k1=sta1.top();sta1.pop();
if(sta1.top()==-99999999)break;
int k2=sta1.top();sta1.pop();
if(sta2.top()=='*'){
k1=k1*k2;
sta1.push(k1);
}
if(sta2.top()=='+'){
k1=k1+k2;
sta1.push(k1);
}
if(sta2.top()=='-'){
k1=k2-k1;
sta1.push(k1);
}
if(sta2.top()=='/'){
k1=k2/k1;
sta1.push(k1);
}
if(sta2.top()==','){
k1=sw(k1,k2);
sta1.push(k1);
}
sta2.pop();//栈顶算符已使用完毕,应出栈;
if(str1[i]==',')//若是,则直接插入;
{
sta2.push(str1[i]);
continue;
}
if(str1[i]!=')'){
sta2.push(str1[i]);
}
else {
if(sta2.top()=='#')break;
if(sta2.top()=='(')sta2.pop();
else i=i-1;//若输入的算符为),但栈顶并不是(,则重复一次
}
}
else if(!bj(sta2.top(),str1[i])){
sta2.push(str1[i]);
}
}
while(sta2.top()!='#'&&sta1.top()!=-99999999)//此时将sta2中的算符进行完
{
int k3=sta1.top();sta1.pop();
if(sta1.top()==-99999999){sta1.push(k3);break;}
int k4=sta1.top();sta1.pop();
if(sta2.top()=='+')k3=k3+k4;
if(sta2.top()=='*')k3=k3*k4;
if(sta2.top()=='-')k3=k4-k3;
if(sta2.top()=='/')k3=k4/k3;
sta1.push(k3);
sta2.pop();
}
cout<<sta1.top()<<endl;
sta1.pop();
}
return 0;
}