nyoj 35 表达式求值

http://acm.nyist.net/JudgeOnline/problem.php?pid=35

《数据结构》的经典例题,中缀式求值

1.先乘除,后加减 

2.同级运算,从左到右 

3.先括号内,后括号外

优先级从大到小:左括号——>乘或除——>加或减——>右括号

将操作数和运算符分别储存在两个栈

思路:

1.操作数栈置为空栈,表达式起始符“=”为运算符栈的栈底元素。

2.从左到右扫描表达式,依次读取表达式的每一个字符,若所读取的字符为“=”,且操作符的栈顶元素也为“=”,

则输出操作数栈的栈顶元素,即为运算结果,结束操作;否则进行下面的处理。

3.若为操作数,入操作数栈,若为操作符,则样将当前操作符和操作符栈的栈顶操作符进行优先级比较。

(1).若当前操作符优先级大于操作符栈的栈顶操作符,则将当前操作符压入操作符栈中;转第2步

(2)若当前操作符优先级等于操作符栈的栈顶操作符,则将当前操作符栈顶的操作符出栈;转第2步

(3)若当前操作符优先级小于操作符栈的栈顶操作符,则将当前操作符栈顶的操作符出栈。并从操作数栈中顺序出栈两个操作数。

用刚出栈的操作符对这两个操作数求值(注意顺序),将所得的值压入操作数栈中。转第2步

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<stack>
using namespace std;
char precede(char s,char z)//判断算术符的优先级
{
	if(s=='+'||s=='-')
	{
		if(z=='*'||z=='/'||z=='(')
			return '<';
		else
			return  '>';
	}
	if(s=='*'||s=='/')
	{
		if(z=='(')
			return '<';
		else
			return '>';
	}
	if(s=='('||s=='=')
	{
		if(s=='('&&z==')'||s=='='&&z=='=') return '=';
		else return '<';
	}
	
}
double operate(double x,int c,double y)//算术符的运算
{
	if(c=='+') return x+y;
	if(c=='-') return x-y;
	if(c=='*') return x*y;
	if(c=='/') return x/y;
}
int main()
{
	int n,len,i,k,flag;
	double x,y;
	char a[1005],b[1005],c;
	scanf("%d",&n);
	while(n--)
	{
		stack<char> tr;
		stack<double> nd; //建立两个栈,tr储存运算符,nd存储double字符串(数字字符 )
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		tr.push('=');//将起始'='作为栈底元素
		flag=0;k=0;
		scanf("%s",a);
		len=strlen(a);
		for(i=0;i<=len-1;)
		{
			if(a[i]=='='&&tr.top()=='=')
				break;
			if(a[i]>='0'&&a[i]<='9'||a[i]=='.')
			{
				b[k++]=a[i];
				i++;
				flag=1;
				continue;
			}
			if(flag==1)
			{
				b[k]='\0';
				nd.push(atof(b));//atof表示将字符串转化为浮点数(double型)
				flag=0;
				k=0;
			}
			switch(precede(tr.top(),a[i]))
			{
			case '<': tr.push(a[i]);i++; break;
			case '=': tr.pop();i++;break;
			case '>': 
				c=tr.top();
				tr.pop();
				y=nd.top();
				nd.pop();
				x=nd.top();
				nd.pop();
				nd.push(operate(x,c,y));
				break;
			}
		}
		printf("%.2lf\n",nd.top());
	}
	return 0;
}


 


 

你可能感兴趣的:(nyoj 35 表达式求值)