程序设计实训报告—表达式求值问题_第1页
程序设计实训报告—表达式求值问题_第2页
程序设计实训报告—表达式求值问题_第3页
程序设计实训报告—表达式求值问题_第4页
程序设计实训报告—表达式求值问题_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、程序设计实训报告一表达式求值问题完成者:何炜班级:计科1501学号:完成日期:2016年7月14日星期四目录、题目的内容及要求错误!未定义书签。二、需求分析错误!未定义书签。三、概要设计错误!未定义书签。四、详细设计错误!未定义书签。五、源代码错误!未定义书签。六、运行结果及分析错误!未定义书签。七、收获及体会错误!未定义书签。一、题目的内容及要求求解形如(a+b)*(c+d)*e+f*h*g)的简单算术表达式的求值问题。 这种表达式只包括加、减、乘、除4种运算符。为了实现表达式求值,可以首先读入原表达式(包括括号)并创 建对应二叉树,其次对二叉树进行前序遍历、中序遍历、后续遍历(非 递归),

2、并输出逆波兰表达式,最后求解原表达式的值,同时对非法 表达式格式能予以判断。用二叉树的结构来存储表达式,后续遍历二叉树即可得到逆波兰 表达式二. 需求分析木程序能解决形如(a+b)*(c+d)*e+f*h*g)兴以帘作为结束标志的直卑 算术表达式的求值问题。不仅能够求解出多位浮点数,而且能够对简单的非法表达式进行判断 以避免程序异常退出。三、概要设计1. 用户输入中缀表达式2. 程序将中缀表达式用二叉树的链式存储结构存储下来3. 前序、中序遍历这颗二叉树,输出对应的前缀、中缀表达式4. 后续遍历(非递归)这颗二叉树,并把遍历结果存储在顺序栈内,并输出后缀表达式5. 对后缀表达式进行求值四、详细

3、设计以下对概要设计进行详细的原理分析。1输入中缀表达式,并存在字符型数组里定义字符串 char strMAXSIZE;通过while(scanf(%s?str)!=EOF)实现用户自定义结束程序的功能 并通过strcmp(leave/str)=O语句实现当用户输入“leave”,程序会 正常退出。以中缀表达式建立一棵二叉树定义二叉树的结构typedef struct BTNodeElemType datalength;struct BTNode *lchild;struct BTNode *rchild;BTNode;其中datalength;存储中缀表达式中的操作数或操作符。整体原理:i.

4、己知输入的 strl=(a+b)*(c+d)*e+f*h*g);定义 BTNode *stMAXSIZE 节点栈,用来存储树的节点。ii. 再定义一个操作符栈char btMAXSIZE存储操作符,去扫描字符串 的每个位置,遇到数字就不做处理直接放到节点栈中,遇到操作 符则将其与操作符栈顶元素比较优先级,决定是否送到节点栈中, 以及决定该节点与其他节点的连接关系。iii. 最后BTNode* &b记录下树的根节点,便得到一颗二叉树了。其中第一、第二步无需过多解释,以下详细解释第二步: 首先通过循环while(bttopl!二#|*p!二#)来扫描字符串的每个位 置的元素 如果字符串该位置为数字

5、,就直接建立树的节点,并把节点放进 节点栈中。这里会遇到两种情况:一种是多位整数,一种是小数/多位整形数:遇到第一位数字时,新建树的节点,存到data 数组里,用while(ln(*p)-O)判断,将后面的几位数字也一起 存到这个节点的也恰数组里,作为一个数字串整体。/带小数点的数:遇到第一位数字时,新建树的节点,存到date 数组里,如果下一位是,.(小数点),,则同样用while(ln(*p)=O) 判断,把小数点后面的数字连同前面的一起存到data数组里, 作为一个数字串整体。代码如下:if(ln(*p)=O)字符串该位置是操作数,则直接建立二义树节点s=(BTNode*)malloc(

6、sizeof(BTNode);slchild二NULL;s-rchild=NULL;s-datai=*p;P+;i+;while(ln(*p)=O)s-datai=*p;PT4;if(*P=T)如果是abc形式,则将a.bc 直存在节点中,直至后面不再 是操作数为止s-datai=*p;i+;P+;while(ln(*p)=O)s-datai=*p;P+;4;s-datai=lO,;top2+;sttop2=s;把该节点放入节点栈内在此之前有一个判断是操作符还是操作数的判断函数,代码如下:int In(charc)if(c二二屮I lc=T lc二二嗦Ilc=/l lc=fl lc二二Tl l

7、c二二#) return 匕操作else return 操作数如果是操作符,则比较该操作符与操作符栈顶元素的优先级 各符号的优先级表如下:ab+*/()+*/(g# 操作符栈顶操作符优先级,则让操作符 入操作符栈,然后检查字符串下一个位置b)如果当前操作符优先级v操作符栈顶操作符优先级,以操作符栈 顶元素建立新的树节点并且取岀节点栈顶的两个节点作为该节点 的左右孩子节点,并把该节点压入节点栈。c)如果当前操作符优先级=操作符栈顶操作符优先级,此时,栈顶 和当前操作符为左右括号,此时,岀操作符栈顶元素,检查字符 串中的下一个元素d)如果返回得到g,即反映了表达式错误,令全局变量error二999

8、, 以便在主函数中控制不输出结果。前序、中序遍历这颗二叉树,并输出前缀、中缀表达式这两种遍历采用递归方式。这种方式很简单。每次访问节点的时候,把节点存在相应表达式数组里,以便输出。后序遍历(非递归)二叉树,并把遍历结果存在字符型指针数组里,并输出后缀表达式非递归后续遍历的思想:采用一个顺序栈才存储需要返回的节点BTNode *StMAXSIZE;,先扫 描根节点所有左孩子节点,并把之前经过的节点一一进栈,到了最后, 出栈一个节点,即为父亲节点,再扫描该节点的右孩子节点的左孩子 节点,并把之前经过的节点一一进栈。当一个节点的左右孩子节点均 访问后再访问该父亲节点,直至栈空为止。当访问该节点的时候

9、,就把该节点数值存放到字符型指针数组里,并 输出该值。通过后缀表达式求出表达式的值因为本程序能解决简单的二目运算符的运算,所以定义double opndl,opnd2作为运算符的两个元素,定义double opnd作为运算结果。定义一个数栈double StMAXSIZE来存放后缀表达式结果。依次扫描后缀表达式(即postexpn数组)i. 如果是数字,同上面建立二叉树一样,分为两种:多位整数和小 数,我们通过循环for(j=0;jvr;j+)(其中r为数字串的长度),只要 发现有小数点,就让flag=l;以此分辨两种情况,并定义k,统计 小数点后而的位数,以便在还原小数的值的时候乘以相应的数

10、量 级即可!还原数字串原本的数值,再讲数值压入到数栈内。ii. 如果是符号,就把数栈内的两个数字取出来(top-)赋值给opndl, opnd2.计算出结果,再压入数栈。通过while(ivn)控制循环条件, 最后StO即为表达式的结果。五、源代码#include #include #include #include /*定义区*/#define MAXSIZE 256#define length 200#define ElemType charint error=0;二义树的链式存储结构 typedef struct BTNode ElemType datalength; struct BT

11、Node *lchild; struct BTNode *rchild;BTNode;判断是操作符还是操作数int ln(char c)if(c=+ 11c=- | |c=* 11c=7 11c=( | |c=)| |c=#) return 1;操作符else return 0;/操作数判断操作符的优先级char Precede(char a,char b)char r;switch(a)casecase ,-:if(b=,*,|b=7,|b=,(,) r=;break; 加减比乘除 和左括号的优先级低casecase7:if(b=()r=,;break;/乘除比左括号的优先级低 case(:

12、if(b=*)左右括号的优先级相同r=,=,;else if(b=#)printf(“表达式错误n”);r=,g,;else r=I;/右括号比其他符号优先级高break;case,#:if(b=,)printf(表达式错误n”);r=g;else if(b=#)r=,=,;else r=lchild=NULL;s-rchild=NULL;s-datai=*p;P+;i+;while(ln(*p)=O)s-datai=*p;P+;i+;if(*p=,.)/如果是a.be形式,则将a.be 一直存在节点中,直至后面不再是操作数为止s-datai=*p;i+;P+;while(ln(*p)=O)/

13、当下一个位置是操作符,就存储到节点数组中s-datai=*p;goto loopl;P+; i+; s-datai=,O,;top2+; sttop2=s;/把该节点放入节点栈内else II字符串该位置是操作符,比较该操作符和操作符栈顶元素的优先 级switch(Precede(bttopl,*p)casetopl+;bttopl=*p;P+;break;如果当前操作符优先级 栈顶操作符优先级,则让操作符 入操作符栈cases=(BTNode*)malloc(sizeof(BTNode);s-datai=bttopl;i+;s-datai=,O,;topi-;s-rchild=sttop2;

14、top2;s-lchild=sttop2;sttop2=s;break;如果当前操作符优先级 data; printf(%s ,b-data); nl+;PreOrder(b-lchild); PreOrder(b-rchild);中序遍历得到前缀表达式char *inexpMAXSIZE;int n2=0;void lnOrder(BTNode *b)讦(b!=NULL)lnOrder(b-lchild); inexpn2=b-data; printf(%s ,b-data); nl+;lnOrder(b-rchild);对二义树进行后序遍历得到后缀表达书后序遍历char* postexpM

15、AXSIZE;/存放后缀表达式,每个节点都是一个字符型数组,故这 里使用字符型指针数组int n3=0;void PostOrder(BTNode *b)BTNode *StMAXSIZE;/保存需要返回节点指针BTNode *p;int flag,top=讦(b!=NULL)dowhile(b!=NULL)top+;Sttop=b; b=b-lchild;p=NULL;flag;while(top!=-l & flag)b=Sttop; if(b-rchild=p)postexpn3=b-data; printf(%s zb-data); n 3+;top;P=b;elseb=b-rchil

16、d; flag 二 0;while(top!=-l);printf(,nH);后缀表达式求值double CompValue()int r;字符串的长度double StMAXSIZE;/数栈double opnd/opndl,opnd2;/opndl,opnd2分别为数栈栈顶的前两个元素, opnd为计算结果char chlength;int top=-l;int i=0;intj;double sum;/不能写成int sum,否则当小数点位数过多,会出现错误!while (in3)strcpy(ch,postexpi);i+;if (strcmp(ch,l,+,)=O)opn dl=St

17、top;top-; opnd2=Sttop;top 一; opnd=opndl+opnd2; top+;Sttop=opnd;else if(strcmp(ch/,J,)=O)opn dl=Sttop;top;opnd2=Sttop;top-; opnd=opnd2-op ndl; top+;Sttop=opnd;else ifjstrcmpfch/1 *)=0)opn dl=Sttop;top-;opnd2=Sttop;top-;opnd=opnd2*opndl;top+;Sttop=opnd;else if(strcmp(ch/,/,)=O)opn dl=Sttop;top-;opnd2=

18、Sttop;top-;if(opndl=0)printf(H不能除以 0nH); error=999;/error为错误变量,以便最后不输出任何结果 retur n 0;opnd=opnd/opndl;top+;Sttop=opnd;elseint k;intflag=O;判断是小数还是多位整数、单位整数三种情况sum =0;r=strlen(ch);for(j=0;jr;j+)讦(chU=7)k=-l;flag=l;elsesum=sum*10+(chj-,0,);k+;top+;if(flag=0)Sttop=sum;elseSttop=sum*pow(10/-k);/ printf(su

19、m=%);/ printf(“还 JM=%fn,l/SttopJ);/ printfr%fnSttop);这个地方如果用“ 就没办法输出浮点 数!return StO;double ExpValuel(BTNode *b)printf(后缀表达式:”);PostOrder(b);return (CompValue();int main ()BTNode床B;根节点的指针 double re;结果变量 char strMAXSIZE;/中缀表达式字符宙printfCprintfC1这里是计算器程序,包含以下功能卍);printfC11.支持二LI运算符的多位整数、单个整数、小数混合的加减乘除卍)

20、; printf(H 2支持对一些简单的非法表达式的判断卍); printf( 3.你可以在任何时候输入leave退出程序n1); printf(u 4.所输入必须是英文符号,以#号键结束! nH);p pj 门 * * * printf(n现在开始! nH);while(scanf(,%s,str)!=EOF)if(strcmp(,leave,str)=O)printf(程序正确退出! n); break;ExpBTree(B,str);/ 建立二义树if(error!=999)printf(n前缀表达式:); PreOrder(B); printfCV);printfC中缀表达式:”);I

21、nOrder(B);printf(n);re=ExpValuel (B);后序遍历并且计算结果printf(运算结果:.2fn”,re);输出结果保留两位小数 nl=O;n2=0;n3=0;error=0;return 1;六、运行结果及分析X* A* A* A*A* A* 十A X A* A* A* A* J* A* A* A* A A A* 右T T *T丫 T* *T 丫 T TT T T T丫丫T T T* 卜T T* T T y T !*这里是计算器程序,包含以下功能1 支持二目运算符的多位整数、单个整数、小数混合的加诫乘除2.支持对一些简单的非法表达式的判断2你可以在任何时候输入仏

22、阮 退出程序4 嶄输人必须是英攵符号,以#号键结束!*卡*: *: *: :*::+:*: :*:*: :+: :*: :*: :*: :+: :+: :+::卡:*:*: *: *: +二:*:现在开始!3+(6*7)+34-1072#前缀表达式:- + + 3*67 34 / 10 2中缀表达式:3 + 6*7 + 34 -10/2后缀裘达式,367* + 34 + 10 2/-运算结果:74. 003+9-8*(4/2)+2#前缀表达式:+ -+ 39*8/422中缀表达式:3 + 9- 8*4/2 + 2后缀表达式:39 + 842/*-2 +运算结果:-2.009-99999999999前缀表达式:-9 99999999999 中缀夷达式:9 - 99999999999 卮缀麦达式:9 99999999999 - 运算结果:-99999999990. 003. 1415*2. 13+21-90#前缀表达式:- + * 31415 2. 13 21 90 中缀表达式:3. 1415 * 2. 13 + 21 - 90 后缀表达式:3. 1415 2. 13 * 21 + 90 - 运算结果:-62314

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论