nyoj1272 zzulioj1923表达式求值(河南省acm第九届省赛)

表达式求值

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 3
描述
假设表达式定义为: 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
来源
河南省第九届省赛
上传者
onlinejudge

和数据结构这本书上的表达式求值类似。

在这里只不过多了smax运算符。仔细分析后我们可以把smax的功能让,来实现。

主要就是处理好运算符的优先级即可~   根据数据结构上的优先级 很快可以找到本题的优先级



然后就是使用栈来模拟操作了、

遍历表达式,每次遇到数字就将这个数入数字栈,如果遇到运算符就和当前栈顶的运算符相比较 ,根据运算符优先级的不同来进行计算。

具体代码如下:

#include <stdio.h>
#include<string.h>
#include<stack>
using namespace std;
char row[]={"+,*()#"};
//运算符优先级 
char mm[10][10]={
				">><<>>",
				"<><<>>",
				">>><>>",
				"<<<<=>",
				">>>=>>",
				"<<<<<="
				};
//取得运算符所有的行号				 
int getRow(char c)
{
	for(int i=0;i<6;i++)
	{
		if(c==row[i])
		return i;
	}
}
//获得优先级 
char getPiro(int x,int y)
{
	return mm[x][y];
}
//smax操作 
int mod(int n)
{
	int sum=0;
	while(n>0)
	{
		sum+=n%10;
		n=n/10;
	}
//	printf("sum=%d \n",sum);
	return sum;
	
} 
//根据不同的运算符 执行不同的操作 
int caculate(int a,int b,char threat)
{
	 switch(threat)
	 {
	 	case '+': return a+b;
	 	case '-': return a-b;
	 	case '*': return a*b;
	 	case ',': return mod(a)>mod(b)?mod(a):mod(b);
 	 }
}
int main()
{
	char str[1050];
	int t;
	stack<int> num; 
	stack<char> op;
	scanf("%d",&t);
	while(t--)
	{
		op.push('#');
		scanf("%s",str);
		int len=strlen(str);
		str[len]='#';
		str[len+1]='\0';
		len++;
		int temp=0;
		bool in=false;
		for(int i=0;i<len;i++)
		{    
			in=false;
			//如果遇到数字  一直执行到读取数字结束 
			while(str[i]>='0'&&str[i]<='9'&&i<len)
			{
				temp=temp*10+str[i]-'0';
				i++;
				in=true;
			}
			if(in) num.push(temp),temp=0;
			//如果遇到运算符 就和当前栈顶的运算符相比较 
			if(str[i]=='+'||str[i]=='-'||str[i]=='*'||str[i]=='('||str[i]==')'||str[i]==','||str[i]=='#')
			{
			//	op.push(str[i]);
				bool exit=true;
				while(exit)
				{
					switch(getPiro(getRow(op.top()),getRow(str[i]))) 
					{
						case '<': op.push(str[i]),exit=false;break;
						case '=': op.pop(),exit=false;break;
						case '>': {
							          char threat =op.top();op.pop();
							          int a=num.top();num.pop();
							          int b=num.top();num.pop();
							      //    printf("%d %c %d\n",a,threat,b);
							          num.push(caculate(a,b,threat));//计算a threat b 
									  break;
						          }
	 				}
	 			}
				
			}
		}
		while(!op.empty()) op.pop();
		printf("%d\n",num.top());num.pop();
	}
	return 0; 
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值