nyoj35 表达式求值
2016-07-09 22:25
435 查看
题目说的很清楚,感觉类似于编译原理的中序表达式求值,定义两个栈,一个存放符号顺序一个存放数值。程序主要就是
1.处理数值,我采用的是一个字符一个字符的输入方式,通过bool isnum(char ch)函数判断输入字符ch是否为数字,是的话分两步走,若之前输入字符中含有小数点‘.’,那么对该字符进行小数处理,如果没有识别到小数点,则按整数部分处理。
在程序识别到下一字符不再是数字的时候,我们将处理好的字符压入数字栈opsign。
2.符号处理。当输入的数据是符号的时候,我们需要判断数字的运算顺序,也就是符号栈中的顺序。基于本人优异的小学数学功底,算术运算的规则自然不在话下:
(1)先乘除,后加减。
(2)从左到右运算。
(3)先算括号内的,再算括号外的。
由于题目所给的测试数据均以“=”结尾,所以等号的优先级是最低的,我们把等号压入栈底,而当“(”与“)”和“=”与“=”相遇时(也就是运算完成),我们需要将他们消除,所以我们定义以上两对优先级相同。至此,我们可以得到优先关系的表,我们用二维数组表示,数值-1表示’<’关系,数值0表示‘=’关系,数值1表示’>’大于关系。数值999表示出错。该二维数组如下:
3.有了优先级表格后,就可以对输入表达式进行匹配了。
首先我们需要将标志匹配完成的“=”压入符号栈中,后逐个读取输入字符,数字就按1所说处理后压入数字栈,若是符号则有以下三个处理规则:
1.当栈顶元素比输入字符优先级低时,即prior[栈顶元素][输入符号]==-1时,将输入符号压入栈中。
2.当括号匹配时,将“(”弹出并接收下一字符。即prior[栈顶元素][输入符号]==0时.
3.当栈顶元素比输入字符优先级高时,即prior[栈顶元素][输入符号]==1时,将运算符op退栈存入变量中,从数据栈先后退出a,b两个数值,计算表达式:b op a = ans 的值,将结果ans压入数据栈。
4.当字符栈元素和输入元素均为“=” 时跳出循环,此时,数据栈顶元素就是要求的结果。
附上完整ac代码
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; }
相关文章推荐
- C#数据结构之顺序表(SeqList)实例详解
- Lua教程(七):数据结构详解
- 解析从源码分析常见的基于Array的数据结构动态扩容机制的详解
- C#数据结构之队列(Quene)实例详解
- C#数据结构揭秘一
- C#数据结构之单链表(LinkList)实例详解
- C++基于栈实现铁轨问题
- 数据结构之Treap详解
- 浅析C语言中堆和栈的区别
- C语言栈的表示与实现实例详解
- C语言实现颠倒栈的方法
- 算法系列15天速成 第十天 栈
- 用C语言举例讲解数据结构中的算法复杂度结与顺序表
- 一看就懂:图解C#中的值类型、引用类型、栈、堆、ref、out
- C#数据结构之堆栈(Stack)实例详解
- C#数据结构之双向链表(DbLinkList)实例详解
- JavaScript数据结构和算法之图和图算法
- Array栈方法和队列方法的特点说明
- Java数据结构及算法实例:冒泡排序 Bubble Sort
- Java数据结构及算法实例:插入排序 Insertion Sort