您的位置:首页 > 理论基础 > 数据结构算法

nyoj35 表达式求值

2016-07-09 22:25 435 查看
题目说的很清楚,感觉类似于编译原理的中序表达式求值,定义两个栈,一个存放符号顺序一个存放数值。程序主要就是

1.处理数值,我采用的是一个字符一个字符的输入方式,通过bool isnum(char ch)函数判断输入字符ch是否为数字,是的话分两步走,若之前输入字符中含有小数点‘.’,那么对该字符进行小数处理,如果没有识别到小数点,则按整数部分处理。

if(ch=='.'){
flag=1;
ch=getchar();
continue;
}
num=ch-'0';//ascii码转换为数值
if(!flag){
intnum=intnum*10+num;//整数处理
}else{
decimal=decimal+num/times;//小数处理
times=times*10;//times初值为10
}


在程序识别到下一字符不再是数字的时候,我们将处理好的字符压入数字栈opsign。

if(!isnum(ch)){
flag=0;times=10;//初始化
intnum=intnum+decimal;//整数部分和小数部分之和
opdata.push(intnum);//压入数字栈
intnum=0;decimal=0;
}


2.符号处理。当输入的数据是符号的时候,我们需要判断数字的运算顺序,也就是符号栈中的顺序。基于本人优异的小学数学功底,算术运算的规则自然不在话下:

(1)先乘除,后加减。

(2)从左到右运算。

(3)先算括号内的,再算括号外的。

由于题目所给的测试数据均以“=”结尾,所以等号的优先级是最低的,我们把等号压入栈底,而当“(”与“)”和“=”与“=”相遇时(也就是运算完成),我们需要将他们消除,所以我们定义以上两对优先级相同。至此,我们可以得到优先关系的表,我们用二维数组表示,数值-1表示’<’关系,数值0表示‘=’关系,数值1表示’>’大于关系。数值999表示出错。该二维数组如下:

int prior[7][7]={1,1,-1,-1,-1,1,1,
1,1,-1,-1,-1,1,1,
1,1,1,1,-1,1,1,
1,1,1,1,-1,1,1,
-1,-1,-1,-1,-1,0,999,
1,1,1,1,999,1,1,
-1,-1,-1,-1,-1,999,0};/*优先级表格{0=>+,1=>-,2=>*,3=>/,4=>(, 5=>),6=>= }*/


3.有了优先级表格后,就可以对输入表达式进行匹配了。

首先我们需要将标志匹配完成的“=”压入符号栈中,后逐个读取输入字符,数字就按1所说处理后压入数字栈,若是符号则有以下三个处理规则:

1.当栈顶元素比输入字符优先级低时,即prior[栈顶元素][输入符号]==-1时,将输入符号压入栈中。

2.当括号匹配时,将“(”弹出并接收下一字符。即prior[栈顶元素][输入符号]==0时.

3.当栈顶元素比输入字符优先级高时,即prior[栈顶元素][输入符号]==1时,将运算符op退栈存入变量中,从数据栈先后退出a,b两个数值,计算表达式:b op a = ans 的值,将结果ans压入数据栈。

4.当字符栈元素和输入元素均为“=” 时跳出循环,此时,数据栈顶元素就是要求的结果。

附上完整ac代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
/*
一些测试数据
7
3*(7-2)=
235.2365+25498.215=
1.01-2=
(1+2)/4=
((1+2)/4+(3-5))*2=
1.000+2/4=
((1+2)*5+1)/4=
*/
int n;
int prior[7][7]={1,1,-1,-1,-1,1,1,
1,1,-1,-1,-1,1,1,
1,1,1,1,-1,1,1,
1,1,1,1,-1,1,1,
-1,-1,-1,-1,-1,0,999,
1,1,1,1,999,1,1,
-1,-1,-1,-1,-1,999,999};/*优先级表格{0=>+,1=>-,2=>*,3=>/,4=>(,
5=>),6=>= }*/
bool isnum(char ch){
if(ch!='='&&ch!='+'&&ch!='-'&&ch!='*'&&ch!='/'&&ch!='('&&ch!=')')return true;
return false;
}
int table(char ch){
switch(ch){
case '+':return 0;
case '-':return 1;
case '*':return 2;
case '/':return 3;
case '(':return 4;
case ')':return 5;
case '=':return 6;
}
}
double oprea(double a,double b,char op){
switch(op){
case '+':return a+b;
case '-':return a-b;
case '*':return a*b;
case '/':return a/b;
}
}
int main(){
scanf("%d",&n);
getchar();
while(n--){
char ch;
double intnum=0;
double decimal=0;
bool flag=0;//判断是整数输入还是小数输入
double times = 10;
double num=0;
stack<double>opdata;//操作数栈
stack<char>opsign;//操作符栈
opsign.push('=');
ch=getchar();
while(ch!='='||opsign.top()!='='){
if(isnum(ch)){
if(ch=='.'){
flag=1;
ch=getchar();
continue;
}
num=ch-'0';
if(!flag){
intnum=intnum*10+num;
}else{
decimal=decimal+num/times;
times=times*10;
}
ch=getchar();
if(!isnum(ch)){
flag=0;times=10;
intnum=intnum+decimal;
opdata.push(intnum);
intnum=0;decimal=0;
}
}else{
int a=table(ch);
int b=table(opsign.top());
switch (prior[b][a]){
case -1:opsign.push(ch);
ch=getchar();
break;
case 0:opsign.pop();
ch=getchar();
break;
case 1:char sign=opsign.top();opsign.pop();
double beh=opdata.top();opdata.pop();
double bef=opdata.top();opdata.pop();
opdata.push(oprea(bef,beh,sign));
break;
}
}
}
printf("%.2lf\n",opdata.top());
getchar();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm 数据结构