栈的应用之表达式求值(算符优先法)
2015-10-30 16:11
465 查看
为了简化问题,我们只考虑+、-、*、/四种运算,他们的优先级规则:
(1)先乘除,后加减
(2)从左算到右
(3)先括号内,再括号外
为了实现算符优先算法,需要两个工作栈,一个用来存放操作数(CZS),一个用来存放运算符(YSF)。
算法的基本思想:
(1)首先置操作数栈、运算符栈均为空,将‘#’压入运算符栈。
(2)依次读入表达式中的每个字符,如果是操作数则直接压入操作数栈(当然,操作数可能不是一位数,可以先用字符串保存每次读入的字符,再转为Int型,压入操作数栈)。如果是运算符,则需要与运算符栈顶元素比较。若运算符栈顶字符的优先级高于当前预算符,出现句柄,需要从操作数栈中弹出两个操作数,从运算符栈顶弹出一个运算符,进行运算后将结果压入操作数栈,注意,此时并没有读入下一个字符,还是用当前字符和栈顶字符比较;若运算符栈顶字符优先级小于当前字符,则直接将当前字符压入运算符栈,读入下一个字符;若运算符栈顶字符的优先级等于当前字符,如’(‘和’)’,则运算符栈弹出一个元素,读入下一个字符。
(1)先乘除,后加减
(2)从左算到右
(3)先括号内,再括号外
为了实现算符优先算法,需要两个工作栈,一个用来存放操作数(CZS),一个用来存放运算符(YSF)。
算法的基本思想:
(1)首先置操作数栈、运算符栈均为空,将‘#’压入运算符栈。
(2)依次读入表达式中的每个字符,如果是操作数则直接压入操作数栈(当然,操作数可能不是一位数,可以先用字符串保存每次读入的字符,再转为Int型,压入操作数栈)。如果是运算符,则需要与运算符栈顶元素比较。若运算符栈顶字符的优先级高于当前预算符,出现句柄,需要从操作数栈中弹出两个操作数,从运算符栈顶弹出一个运算符,进行运算后将结果压入操作数栈,注意,此时并没有读入下一个字符,还是用当前字符和栈顶字符比较;若运算符栈顶字符优先级小于当前字符,则直接将当前字符压入运算符栈,读入下一个字符;若运算符栈顶字符的优先级等于当前字符,如’(‘和’)’,则运算符栈弹出一个元素,读入下一个字符。
# include<stdio.h> # include<stdlib.h> # include<string.h> # define MAX 100 //运算符 typedef struct{ char data[MAX]; int top; }Operator; //操作数 typedef struct{ int data[MAX]; int top; }Operand; int operate(int a,char theta,int b); void InitStack(Operator &s); void InitStack(Operand &s); int Push(Operator &s,char c); int Push(Operand &s,int a); int Pop(Operator &s); int Pop(Operand &s); char getTop(Operator &s); int getTop(Operand &s); char Precede(char a,char b); int main() { Operator YSF;//运算符栈 Operand CZS;//操作数栈 char num[15]; InitStack(CZS); InitStack(YSF); Push(YSF,'#'); printf("-------四则运算(加减乘除),输入以#号结束--------\n"); char ch=getchar(); while(ch!='#'||getTop(YSF)!='#') { int i=0,a,b,flag=0; char theta; while(ch>='0'&&ch<='9') { flag=1; num[i++]=ch; ch=getchar(); } if(flag) { num[i]='\0'; Push(CZS,atoi(num)); } if(ch<'0'||ch>'9') { switch(Precede(getTop(YSF),ch)) { case '>': theta=getTop(YSF); Pop(YSF); b=getTop(CZS); Pop(CZS); a=getTop(CZS); Pop(CZS); Push(CZS,operate(a,theta,b)); break; case '=': Pop(YSF); ch=getchar(); break; case '<': Push(YSF,ch); ch=getchar(); break; } } } printf("%d\n",getTop(CZS)); return 0; } int operate(int a,char theta,int b) { if(theta=='+') return a+b; else if(theta=='-') return a-b; else if(theta=='*') return a*b; else if(theta=='/') return a/b; } void InitStack(Operator &s) { memset(s.data,0,MAX*sizeof(char)); s.top=0; } void InitStack(Operand &s) { memset(s.data,0,MAX*sizeof(int)); s.top=0; } int Push(Operator &s,char c) { if(s.top>=MAX) return 0; else { s.data[s.top]=c; s.top++; return 1; } } int Push(Operand &s,int a) { if(s.top>=MAX) return 0; else { s.data[s.top]=a; s.top++; return 1; } } int Pop(Operator &s) { if(s.top==0) return 0; else { s.top--; s.data[s.top]=0; return 1; } } int Pop(Operand &s) { if(s.top==0) return 0; else { s.top--; s.data[s.top]=0; return 1; } } char getTop(Operator &s) { return s.data[s.top-1]; } int getTop(Operand &s) { return s.data[s.top-1]; } //比较两个运算符的优先级,a运算符在b左边 char Precede(char a,char b) { if(a=='+'||a=='-') { if(b=='+'||b=='-'||b==')'||b=='#') return '>'; else return '<'; } else if(a=='*'||a=='/') { if(b=='(') return '<'; else return '>'; } else if(a=='(') { if(b=='+'||b=='-'||b=='*'||b=='/'||b=='(') return '<'; else if(b==')') return '='; else { printf("输入有误"); return 0; } } else if(a==')') { if(b=='+'||b=='-'||b=='*'||b=='/'||b==')'||b=='#') return '>'; else if(b=='(') { printf("输入有误"); return 0; } } else if(a=='#') { if(b==')') { printf("输入有误"); return 0; } else if(b=='#') return '='; else return '<'; } }
相关文章推荐
- java调用批处理(doc)执行多条命令
- uploadify+jcrop实现头像上传裁剪功能
- 堆
- 第20章 多任务和多线程
- PL/SQL下载安装
- 《java8函数式编程》——使用函数式编程重构代码
- 第一天
- ios动画
- <iOS>系统提供的dispatch方法
- 二分查找
- Scrapy--1安装和运行
- 既然决定学习python就开始记录一些问题吧
- 欢迎使用CSDN-markdown编辑器
- 【C语言学习】《C Primer Plus》第13章 文件输入/输出
- 事件分发机制
- Spring 和 MyBatis 环境整合
- apk反编译
- Address already in use - bind(二) (Errno:EADDRINUSE)
- 简单词法分析器的实现
- JS对于Android和IOS平台的点击响应的适配