表达式求值(顺序栈实现)
来源:互联网 发布:c语言中a=3是什么意思 编辑:程序博客网 时间:2024/06/04 20:00
问题:算数运算的表达式求知
这道题不难,但是当你认真去编代码的时候,还是要考虑好多细节。
算法原理如下:
我们都知道算术四则运算的运算规则是:
先乘除,后加减。
从左到右计算
先算括号内,再算括号外
表达式组成
任何一个表达式都有操作数、运算符和界定符组成。
操作数即可以是常量,也可以是被说明为变量或常量的标识符。
运算符可以分为算术运算,关系运算和逻辑运算符。
界定符有左右括号和结束符等。
本文为了方便演示只使用算术运算。
运算符优先级
对于连个相继出现的操作符θ1和θ2 有三种关系:大于、等于和小于。由此可以列出“+-*/”之间的优先级。如下表:
+-*/()#+>><<<>>->><<<>>*>>>><>>/>>>><>>(<<<<<=
)>>>>
>>#<<<<<
=
加减乘除优先性都低于“(”但是高于“)”,由运算从左到右可知,当θ1=θ2 ,令θ1>θ2
为了算法简洁,在表达式的左边和右边虚设一个“#”,这一对“#”表示一个表达式求值完成。
“(”=“)”当一对括号相遇时表示括号内已运算完成。
“)”和“(”、“#”和“(”、“(”和“#”无法相继出现如果出现则表达式出现语法错误。
为实现优先算法,可以使用两个工作栈,一个是OPTR,用于寄存运算符,一个是OPND,用于寄存运算数和运算结果。
代码如下:(存在一个bug)
#include<stdio.h> //表达式求值,顺序栈 #include<stdlib.h>#define STACK_INIT_SIZE 100#define STACKINCREMENT 10#define OK 1#define ERROR 0typedef int Status;typedef struct{char * base;char * top;int stacksize; }SqStack;//函数声明..................................Status InitStack(SqStack &S); //符号栈的建立 Status Push(SqStack &S,char e); //入栈 void OperandType_EvaluateExpression(SqStack &OPND,SqStack &OPTR);char GetTop(SqStack S); //返回栈顶元素 Status Pop(SqStack &S,char &e); //出栈 Status IsDigit(char c); //判断是否为数字 char Precede(char a,char e); //符号优先级判断, int swap_char_to_int(char a); //在Precede中的字符转换为数字函数 char Operate(char a,char x,char b); //运算函数,返回为char型的数字 Status shownumbers(SqStack S);//函数实现........................................... Status InitStack(SqStack &S){S.base = (char *)malloc(STACK_INIT_SIZE * sizeof(char));if(!S.base)exit(ERROR);S.top = S.base;S.stacksize = STACK_INIT_SIZE;return OK;}Status Push(SqStack &S,char e){if(S.top - S.base >= S.stacksize){S.base = (char *)realloc(S.base,(S.stacksize + STACKINCREMENT) * sizeof(char));if(!S.base)exit(ERROR);S.top = S.base + S.stacksize;S.stacksize += STACKINCREMENT;}*S.top = e;S.top++;return OK;}void OperandType_EvaluateExpression(SqStack &OPND,SqStack &OPTR){char c;char x;char b;char a;Push(OPTR,'#');c = getchar();while(c != '#' || GetTop(OPTR) != '#'){if(IsDigit(c)) //若是数字则进数字栈,不是判断符号优先级 {Push(OPND,c);c = getchar();}else{switch(Precede(GetTop(OPTR),c)){case '<':Push(OPTR,c);c = getchar();break;case '=':Pop(OPTR,x);c = getchar();break;case '>':Pop(OPTR,x);Pop(OPND,b);Pop(OPND,a);Push(OPND,Operate(a,x,b));break;//printf("") }} }/*char sum;sum = GetTop(OPND);printf("%c\n",sum);shownumbers(OPND);printf("\n");shownumbers(OPTR); */}char GetTop(SqStack S){char e;if(S.top == S.base)exit(-1);elsee = *(S.top-1);return e;}Status Pop(SqStack &S, char &e){if(S.base == S.top)return ERROR;elsee = *--S.top;return OK; } Status IsDigit(char c){if(c >= '0' && c <= '9')return 1;elsereturn 0;}char Precede(char a,char e){int i,j;int flag;int symbol[7][7] = {{0,0,1,1,1,0,0},{0,0,1,1,1,0,0},{0,0,0,0,1,0,0},{0,0,0,0,1,0,0},{1,1,1,1,1,2,4},{0,0,0,0,4,0,0},{1,1,1,1,1,4,2},}; i = swap_char_to_int(a);j = swap_char_to_int(e);flag = symbol[i][j];switch(flag){case 0:return '>';case 1:return '<';case 2:return '=';case 4:exit(-1);}} int swap_char_to_int(char a){switch(a){case '+':return 0;case '-':return 1;case '*':return 2;case '/':return 3;case '(':return 4;case ')':return 5;case '#':return 6;}} char Operate(char a,char x,char b){int c,d;int sum;c = a-'0';d = b-'0';switch(x){case '+':sum = c+d;break;case '-':sum = c-d;break;case '*':sum = c*d;break;case '/':sum = c/d;break;}return sum+'0';} Status shownumbers(SqStack S){int numbers = 1;if(S.top == S.base){printf("栈为空栈,无法打印\n");exit(-1);}while(S.base < S.top){S.top--;printf("%c ",*S.top);numbers++;}}//驱动函数..................int main(){int sum;SqStack OPTR; //符号栈 SqStack OPND; //数字栈InitStack(OPTR);InitStack(OPND);OperandType_EvaluateExpression(OPND,OPTR);sum = GetTop(OPND) - '0';printf("%d",sum); return 0; }
运行结果如下:
1*2+6/2*(2+3*5)#
53--------------------------------
Process exited after 16.61 seconds with return value 0
请按任意键继续. . .
存在BUG如下:
1,输入的整数必须小于10.
2,不能输入小数,除数必须大于被除数。
分析:
1.代码中由于通过getchar()读取,所以当输入10/5的时候,读取的其实是1 和 0 两个字符。
2.这个是因为int型的除法问题,比如当3/7的时候,并不是小数,而是得0。
对于的一个bug,我想到的是,可以在输入的时候,建立数组完成,但是这个会导致输入有限,或者继续用getchar()输入,输入后进行数字的判断来解决,想一想是可以实现的。如果是连续的数字,就累加,终止条件是下一个符号。
对于第二个bug,则是要建立float型的数据类型,把char型转换为float型,但是或许又潜在的问题?并没有尝试。
- 算术表达式求值(顺序栈实现)
- 表达式求值(顺序栈实现)
- 顺序栈实现表达式求值
- 顺序栈实现表达式求值
- 【新手 表达式求值】 顺序栈实现表达式求值
- 后缀表达式求值(顺序栈)
- 表达式求值(栈实现)
- 栈实现表达式求值
- 栈实现表达式求值
- 栈实现表达式求值
- 表达式求值(栈实现)
- 表达式求值程序(用栈实现)
- C++实现任意表达式求值(栈)
- nyoj 305 表达式求值 (栈实现)
- 栈实现表达式求值(C语言)
- 表达式求值--栈(c++/java实现)
- 栈实现表达式求值(C语言)
- C语言 算数表达式求值(顺序栈应用实例)
- 正则表达式
- JavaScript利用对象去重复值
- MySQL B+树索引和哈希索引的区别
- 图的最小生成树算法
- Spring的AOP原理
- 表达式求值(顺序栈实现)
- 6. ZigZag Conversion
- Backtrader量化平台教程(二):Strategy类
- jvm
- Spark RPC之RpcEnvFileServer
- 设计模式学习--解释器模式
- pycharm搭建django
- 动态联编/运行时联编和静态联编
- Error Function in PeopleSoft