数据结构算术表达式求值系统论文.docx
- 文档编号:8698189
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:14
- 大小:44.17KB
数据结构算术表达式求值系统论文.docx
《数据结构算术表达式求值系统论文.docx》由会员分享,可在线阅读,更多相关《数据结构算术表达式求值系统论文.docx(14页珍藏版)》请在冰豆网上搜索。
数据结构算术表达式求值系统论文
算术表达式求值系统
1引言
算术表达式求值是实现程序设计语言的基本问题之一,也是栈的应用的一个典型例子。
本课程设计是关于算术表达式求值的一套系统,该系统通过运用栈实现了对从键盘输入的算术表达式求出正确的结果,而且能够显示出输入的算术表达式序列以及栈的变化过程。
任何一个算术表达式都是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。
要实现用计算机来对算术表达式求值,不可能按照我们平时计算算术表达式那样,从左往右计算算术表达式,那么我们运用算符优先算法能够解决这个问题。
为实现算符优先算法,我们使用了两个操作栈:
一个是操作符栈OPTR,用于存放操作符;另一个是操作数栈OPND,用于存放操作数及运算结果。
该系统首先利用栈将中缀表达式转换成后缀表达式,接着用栈对后缀表达式求值。
所以我们只需从键盘输入一个合法的算术表达式,系统就能输出正确的结果,同时显示出算术表达式序列和栈的变化过程。
本系统是采用C语言编写的。
另外,运用栈这种数据结构实现了计算机对算术表达式的求值。
在解决实际问题中运用到了栈这种数据结构,能够让我们深入了解栈的特性,同时加深对这种结构的理解和认识。
2需求分析
2.1可行性分析
可行性分析的含义就是用最小的代价和尽可能少的时间来解决问题。
而算术表达式求值系统正好实现了缩短时间、提高效率、减少财力的支出而完成任务的目的。
本系统采用C语言实现了对表达式的输入、转换、求值以及运算结果的输出等功能的设计,用栈这种数据结构实现了算符优先算法,从而实现了技术上的可行性。
在当今的信息时代,计算机已为日常办公所用,操作系统也为人们所熟悉。
购买计算机所需费用也能够被人们所接受。
只要一台电脑,这个系统就可以实现其功能。
本系统可以减少用户的工作量,提高工作效率,而且它有着简单、直观、适用、操作方便等优点。
2.2需求规定
2.2.1对功能的规定
用栈数据结构完成一个算术表达式求值系统,此系统的具体功能要求如下:
(1)表达式输入功能:
一个算术表达式,由常量、运算符和括号组成(以字符串形式输入)。
为简化,规定操作数只能为正整数,操作符为+、-、*、/、(、)、#。
(2)表达式转换功能:
设置运算符栈和运算数栈辅助分析算符优先关系。
在读入表达式的字符序列的同时,完成运算符和运算数的识别处理,从而实现了将中缀表达式转换成后缀表达式。
(3)表达式求值及运算结果输出功能:
用栈对后缀表达式求值,并将表达式的运算结果输出。
3概要设计
在计算机中,算术表达式由常量、运算符和括号组成。
由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行。
每次操作的数据或运算符都是最近输入的,这与栈的特性相吻合,故本课程设计借助栈来实现按运算符的优先级完成表达式的求值计算。
3.1算法设计
(1)算符的优先级比较函数Precede(SElemTypet1,SElemTypet2)
1.算法的基本思想:
通过已知的算符间的优先关系写出算符的优先级算法。
任意两个相继出现的算符c1和c2之间的优先关系至多是下面3种关系之一:
1)c1 2)c1=c2c1的优先权等于c2 3)c1>c2c1的优先权高于c2 2.算法步骤: 2.1如果输入符号为“+”或“-” 2.1.1如果栈顶元素为“(”、“#”,此时栈顶符号优先级低,返回“<” 2.1.2否则,栈顶符号优先级高,返回“>” 2.2如果输入符号为“*”或“/” 2.2.1如果栈顶元素为“)”、“*”、“/”,此时栈顶符号优先级高,返回“>” 2.2.2否则,栈顶符号优先级低,返回“<” 2.3如果输入符号为“(”,则直接返回“<” 2.4如果输入符号为“)” 2.4.1如果栈顶元素为“(”,此时优先级同,返回“=” 2.4.2否则,栈顶符号优先级高,返回“>” 2.5输入符号为其他 2.5.1栈顶元素为“#”,此时优先级同,返回“=” 2.5.2否则,栈顶符号优先级高,返回“>” (2)确定如何入栈函数EvaluateExpression() 1.算法的基本思想: 1.1首先置操作数栈为空栈,表达式起始符“#”为运算符栈的栈底元素。 1.2依次读入表达式中每个字符,若是操作数则进运算数栈,若是运算符则和运算符栈的栈顶运算符比较优先后作相应操作,直至整个表达式求值完毕(即运算符的栈顶元素和当前读入的字符均为“#”)。 2.算法步骤: 2.1将‘#’入栈,作为低级运算符 2.2输入不含变量的表达式(以#结束) 2.3如果c! ='#'||x! ='#' 2.3.1如果输入的是运算符 2.3.1.1比较运算符的优先级 1)栈顶元素优先级低,则入栈且继续输入 2)栈顶元素优先级相等,脱括号并接收下一字符 3)栈顶元素优先级高,则退栈并将运算结果入栈 2.3.2如果输入的是运算数 2.3.1.1如果输入的是单个运算数,则将该运算数存入数组中,把它看成是一个字符串,并将它转换成整型,然后压入操作数栈 2.3.1.2如果输入的是连续数字,则将该连续数字存入数组中,把它看成是一个字符串,并将它转换成整型,然后压入操作数栈 2.3.3如果输入的是非法字符,则打印“出现非法字符” 2.4如果c和x都为'#' 2.4.1如果运算数栈OPND不空(运算符栈OPTR仅剩'#'),则打印“表达式不正确” 2.4.2否则将运算数栈OPND的栈顶元素弹出,并附到x中,再将x值返回 3.2基本模块介绍 算术表达式求值系统可以分为三个模块: 1.表达式输入功能模块——将表达式序列输入系统中 2.表达式转换功能模块——实现将中缀表达式转换成后缀表达式 3.表达式求值功能模块——实现表达式求值并输出运算结果 图1功能模块图 4详细设计 4.1栈的顺序存储表示 typedefstruct {charstack[100]; inttop; }SqStack; typedefcharSElemType; 4.2基本操作函数 voidInitStack(SqStack&S)//栈建立函数 intStackEmpty(SqStackS)//判断栈是否为空 SElemTypeEvaluateExpression()//确定如何入栈函数 voidPush(SqStack&S,SElemTypee)//入栈函数 intGetTop(SqStackS,SElemType&e)//取栈顶元素函数 intPop(SqStack&S,SElemType&e)//出栈函数 charPrecede(SElemTypet1,SElemTypet2)//比较函数 intIn(SElemTypec)//判断c是否为7种运算符之一 SElemTypeOpearte(SElemTypea,SElemTypetheta,SElemTypeb)//运算函数 voidDispStack1(SqStackS)//从栈底到栈顶依次输出各元素(运算符栈) voidDispStack2(SqStackS)//从栈底到栈顶依次输出各元素(运算数栈) 4.3源程序清单 #include"stdio.h" #include"stdlib.h" typedefstruct {charstack[100]; inttop; }SqStack; typedefcharSElemType; voidInitStack(SqStack&S) {S.top=0;} intStackEmpty(SqStackS) {//若栈S为空栈,则返回TRUE,否则返回FALSE if(S.top==0) return1; else return0; } intGetTop(SqStackS,SElemType&e) {//若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR if(S.top>0) { e=S.stack[S.top-1]; return1; } else return-1; } voidPush(SqStack&S,SElemTypee) {//插入元素e为新的栈顶元素 if(S.top>100)//栈满, { printf("栈满,出错! "); } else S.stack[S.top++]=e; } intPop(SqStack&S,SElemType&e) {//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR if(S.top==0) return-1; e=S.stack[--S.top]; return1; } charPrecede(SElemTypet1,SElemTypet2) {//根据教科书表3.1,判断t1,t2两符号的优先关系('#'用'\n'代替) charf; switch(t2) { case'+': case'-': if(t1=='('||t1=='\n') f='<';//t1 else f='>';//t1>t2 break; case'*': case'/': if(t1=='*'||t1=='/'||t1==')') f='>';//t1>t2 else f='<';//t1 break; case'(': if(t1==')') { printf("括号不匹配\n"); exit(0); } else f='<';//t1 break; case')': switch(t1) { case'(': f='=';//t1=t2 break; case'#': printf("缺乏左括号\n"); exit(0); default: f='>';//t1>t2 } break; case'#': switch(t1) { case'#': f='=';//t1=t2 break; case'(': printf("缺乏右括号\n"); exit(0); default: f='>';//t1>t2 } } returnf; } intIn(SElemTypec) {//判断c是否为7种运算符之一 switch(c) { case'+': case'-': case'*': case'/': case'(': case')': case'#': return1; default: return0; } } SElemTypeOpearte(SElemTypea,SElemTypetheta,SElemTypeb) {//做四则运算athetab,返回运算结果 switch(theta) { case'+': returna+b; case'-': returna-b; case'*': returna*b; } returna/b; } voidDispStack1(SqStackS)//从栈底到栈顶依次输出各元素(运算符栈) { chare; intp; if(S.top==0) printf(""); else { p=0; while(p { e=S.stack[p]; p++; printf("%c",e); } } } voidDispStack2(SqStackS)//从栈底到栈顶依次输出各元素(运算数栈) { chare; intp; if(S.top==0) printf(""); else { p=0; while(p { e=S.stack[p]; p++; printf("%d",e); } } } SElemTypeEvaluateExpression() {//算术表达式求值的算符优先算法。 设OPTR和OPND分别为运算符栈和运算数栈 SqStackOPTR,OPND; SElemTypea,b,d,x; charc;//存放由键盘接收的字符 charz[11];//存放整数字符串 inti; intn=1;//步骤 InitStack(OPTR);//初始化运算符栈OPTR和运算数栈OPND InitStack(OPND); Push(OPTR,'#');//将换行符压入运算符栈OPTR的栈底(改) c=getchar();//由键盘读入1个字符到c printf("\n对表达式求值的操作过程如下: "); printf("\n_______________________________________________________________\n"); printf("步骤\t运算符栈OPTR\t运算数栈OPND\t主要操作"); GetTop(OPTR,x);//将运算符栈OPTR的栈顶元素赋给x while(c! ='#'||x! ='#')//c和x不都是"#" { printf("\n______________________________________________________________\n"); printf("%d\t",n++); DispStack1(OPTR); printf("\t\t"); DispStack2(OPND); printf("\t\t"); if(In(c))//c是7种运算符之一 switch(Precede(x,c))//判断x和c的优先权 { case'<': Push(OPTR,c); printf("Push(OPTR,%c)",c); c=getchar(); break; case'=': printf("Pop(OPTR){消去一对括号}"); Pop(OPTR,x);//x='('且c=')'情况,弹出'('给x(后又扔掉) c=getchar();//由键盘读入下一个字符到c(扔掉')') break; case'>': Pop(OPTR,x); Pop(OPND,b); Pop(OPND,a); Push(OPND,Opearte(a,x,b));//做运算axb,并将运算结果入运算数栈 printf("Opearte(%d,%c,%d)",int(a),x,int(b)); } elseif(c>='0'&&c<='9')//c是操作数 { i=0; while(c>='0'&&c<='9')//是连续数字 { z[i++]=c; c=getchar(); } z[i]=0;//字符串结束符 d=atoi(z);//将z中保存的数值型字符串转为整型存于d printf("Push(OPND,%d)",d); Push(OPND,d);//将d压入运算数栈OPND } else//c是非法字符 { printf("\n______________________________________________________________\n"); printf("\n出现非法字符\n"); exit(0); } GetTop(OPTR,x);//将运算符栈OPTR的栈顶元素赋给x } printf("\n______________________________________________________________\n"); printf("%d\t",n++); DispStack1(OPTR); printf("\t\t"); DispStack2(OPND); printf("\t\t"); printf("RETURN(GetTop(OPND))"); printf("\n______________________________________________________________\n"); Pop(OPND,x);//弹出运算数栈OPND的栈顶元素(运算结果)给x if(! StackEmpty(OPND))//运算数栈OPND不空(运算符栈OPTR仅剩'#') { printf("\n表达式不正确\n"); exit(0); } returnx; } voidmain() { printf("请输入算术表达式,负数要用(0-正数)表示(以#结束): \n"); printf("\n算术表达式的求值结果为: %d\n",EvaluateExpression()); } 5系统实现 将源程序放到VisualC++6.0的环境上进行调试,调试成功后就可输入一个算术表达式,然后系统就可以显示出算术表达式的正确结果以及栈的变化过程。 例如输入: 3*(5+2)# 可以得到如下图所示结果: 图2算术表达式运行结果 6结束语 经过一段时间的实际操作和搜索相关资料,终于让我完成了本次课程报告。 让我对数据结构有了更进一步的认识和了解,也让我知道,要想学好它,要重在实践,理论与实际应用相结合,同时提高了自己组织数据及编写大型程序的能力,培养了基本的、良好的程序设计技能。 通过实际操作,我也发现我的好多不足之处: (1)用栈的结构来解决表达式的求值,首先要解决的问题是如何将人们习惯书写的表达式转换成计算机容易处理的表达式。 开始有些茫然,后来通过结合课本完成了该课程报告。 (2)对一些看似简单的东西掌握不够熟练,比如由于函数的调用参数问题不熟而造成了调试的困难。 对于语法的掌握也欠缺成熟,需要进一步掌握。 (3)栈的结构理解不够清晰,造成了设计程序时理不清头绪,所以之后需要对数据结构有更深层次的理解。 (4)我因为不注重细节而使得运行结果发生错误: 因为没有对中英文输入进行切换。 这一点小小的错误也耽误了我几十分钟,所以说细节决定成败。 参考文献: [1]严蔚敏,吴伟民.《数据结构》(C语言版).清华大学出版社2002 [2]严蔚敏,吴伟民.《数据结构习题集》(C语言版).清华大学出版社2002 [3]许卓群.《数据结构与算法》.高等教育出版社2004
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 算术 表达式 求值 系统 论文
![提示](https://static.bdocx.com/images/bang_tan.gif)