数据结构课程设计-表达式求值问题

合集下载

算术表达式的求解-数据结构课程设计报告

算术表达式的求解-数据结构课程设计报告

课程设计报告题目:算术表达式求值一、需求分析1、设计要求:给定一个算术表达式,通过程序求出最后的结果1>、从键盘输入要求解的算术表达式;2>、采用栈结构进行算术表达式的求解过程;3>、能够判断算术表达式正确与否;4>、对于错误表达式给出提示;5>、对于正确的表达式给出最后的结果;2、设计构想:为了实现算符优先算法使用两个工作栈,一个称作OPTR,以寄存运算符;另一个称作OPND,用以寄存操作数或运算结果。

在操作数和操作符入栈前,通过一个函数来判别,输入的是操作数还是操作符,操作数入OPND,操作符入OPTR。

在输入表达式的最后输入‘#’,设定‘#’的优先级最低,代表表达式输入结束。

在表达式输入过程中,遇操作数则直接入栈,遇到运算符则与栈顶运算符比较优先级,若当前运算符优先级高,则当前运算符入栈,扫描下一符号;否则栈顶运算符出栈,两操作数出栈,进行运算,所得结果入数栈,重新比较当前运算符与新栈顶运算符。

如此重复直到栈顶运算符与当前符号均为‘#’,运算结束。

二、概要设计1、本程序包含的模块:(1)栈模块——实现栈抽象数据类型(2)运算模块——实现数据表达式的运算(3)主程序模块三、详细设计(1)栈模块1、定义栈结构struct Sqstack{elemtype *top;//栈顶元素elemtype *base; //栈底元素int stacksize;//栈的大小};2、栈的基本操作①初始化栈status initstack(struct Sqstack &s){s.base=(elemtype *)malloc(stack_size*sizeof(elemtype)); if(!s.base)return OVERFLOW;s.top=s.base;s.stacksize=stack_size;return OK;}②入栈status push(struct Sqstack &s,elemtype e){if(s.top-s.base>=s.stacksize){s.base=(elemtype*)realloc(s.base,(s.stacksize+stack_increase ment)*sizeof(elemtype));if(!(s.base))return OVERFLOW;s.top=s.base+s.stacksize;s.stacksize+=stack_increasement;}* s.top++=e;return OK;}③出栈elemtype pop(struct Sqstack &s){elemtype e;if(s.top= =s.base)return ERROR;e=*--s.top;return e;}④取栈顶元素elemtype gettop(struct Sqstack &s){elemtype e;if(s.top==s.base)return ERROR;e=*(s.top-1);return e;}(2)运算模块1、判断输入字符c是否为操作符:若是,则返回1;否则,返回0int In(int c){char p[10]="+-*/()#^";int i=0;while(p[i]!='\0'){if(p[i]==c)return 1;i++;}return 0;}2、判断运算符的优先级char precede(char top,char c)//该函数为判断当前运算符与前一个运算符的优先级,前一个运算符高于或等于当前运算符的优先级则返回‘>’,前一个运算符小于当前运算符的优先级则返‘<’,当前一个运算符为‘(’当前运算符为‘)’时返回‘=’,用于去除表达式的括号。

算术表达式的求解-数据结构课程设计报告

算术表达式的求解-数据结构课程设计报告

算术表达式的求解-数据结构课程设计报告课程设计报告题目:算术表达式求值一、需求分析 1、设计要求:给定一个算术表达式,通过程序求出最后的结果 1>、从键盘输入要求解的算术表达式; 2>、采用栈结构进行算术表达式的求解过程; 3>、能够判断算术表达式正确与否;4>、对于错误表达式给出提示;5>、对于正确的表达式给出最后的结果; 2、设计构想:为了实现算符优先算法使用两个工作栈,一个称作OPTR,以寄存运算符;另一个称作OPND,用以寄存操作数或运算结果。

在操作数和操作符入栈前,通过一个函数来判别,输入的是操作数还是操作符,操作数入OPND,操作符入OPTR。

在输入表达式的最后输入‘#’,设定‘#’的优先级最低,代表表达式输入结束。

在表达式输入过程中,遇操作数则直接入栈,遇到运算符则与栈顶运算符比较优先级,若当前运算符优先级高,则当前运算符入栈,扫描下一符号;否则栈顶运算符出栈,两操作数出栈,进行运算,所得结果入数栈,重新比较当前运算符与新栈顶运算符。

如此重复直到栈顶运算符与当前符号均为‘#’,运算结束。

二、概要设计1、本程序包含的模块:栈模块——实现栈抽象数据类型运算模块——实现数据表达式的运算主程序模块算术运算式的求解栈模块主函数模块main 运算模块定义栈结构初始化栈出栈入栈取栈顶元素判断输入字符类型判断符号优先级基础运算函数运算函数三、详细设计栈模块1、定义栈结构 struct Sqstack{elemtype *top;//栈顶元素 elemtype *base; //栈底元素 int stacksize;//栈的大小 };2、栈的基本操作①初始化栈status initstack(struct Sqstack &s) {=(elemtype *)malloc(stack_size*sizeof(elemtype)); if(!) return OVERFLOW; =;=stack_size; return OK; } ②入栈status push(struct Sqstack &s,elemtype e) {if(>=) {=(elemtype*)realloc(,(+stack_increasement)*sizeof(elemtype));if(! ) return OVERFLOW; =+; +=stack_increasement; } * ++=e; return OK; } ③出栈elemtype pop(struct Sqstack &s) {elemtype e; if(= =) return ERROR; e=*--;return e; }④取栈顶元素elemtype gettop(struct Sqstack &s) {elemtype e; if(==) return ERROR; e=* ; return e; } 运算模块1、判断输入字符c是否为操作符:若是,则返回1;否则,返回0 int In(int c) {char p[10]=\ int i=0;while(p[i]!='\\0') {if(p[i]==c) return 1;i++; } return 0; }2、判断运算符的优先级char precede(char top,char c)//该函数为判断当前运算符与前一个运算符的优先级,前一个运算符高于或等于当前运算符的优先级则返回‘>’,前一个运算符小于当前运算符的优先级则返‘'; break; case '+': case '-':if(top=='#'||top=='(')result=''; break; case '*': case '/':if(top=='*'||top=='/'||top=='^') result='>'; elseresult=''; elseresult=''; break;case '(': result='': theta=pop(optr); b=pop(opnd); a=pop(opnd); push(opnd,operate(a,theta,b)); break;// 若当前操作符的优先级低于操作符栈的栈顶元素,则将操作符栈栈顶元素出栈,并将操作数栈的栈顶两个元素出栈,计算两个元素间以操作符栈栈顶元素为运算符的数学运算}//switch }//if}//whilereturn pop(opnd); }主程序模块1、main函数void main(int argc,char *argv) {struct Sqstack opnd; //操作数栈 struct Sqstack optr;//操作符栈initstack(opdn); initstack(optr); elemtype result;printf(\ printf(\算术运算式的求解\printf(\ printf(\请输入算术运算表达式(以'#'结尾):\\n\ printf(\result=evaluate(opnd,optr);printf(\printf(\运算的结果是 :\\n \\n%d\\n\printf(\}四、调试分析 1、测试结果1> 测试数据:3+7*2-1# 测试结果:2> 测试数据:(3+7)*2-1# 测试结果:3> 测试数据: 1/0# 测试结果:2、程序时间复杂度为O;3、设计中出现的问题:在开始的设计中没有注意除数不能为0 ,后来加入if(b==0) {printf(\分母为0,the result is error\\n\ result=0; } elseresult=a/b;break;来判断除数是否为0 4、算法改进:1>输入的操作数和操作码于是字符串类型的,在原设计中实现的操作都是对个位数实现的,实用性不大,故在后来的设计中,通过一个标志flag实现了标志操作数的连续输入的判别,继而实现了多位数的表达式运算2>开始只实现了加、减、乘、除及带小括号的数学运算,考虑到实用性,在后来的设计中引入pow函数,实现了乘方的运算,调整结果如下:3>最初设计的运行界面过于单调,不够友好,改进时加入一些*调整调整结果如下:五、课程设计总结本学期是我第一次接触课程设计,发现了很多学习上的问题,也有很多收获。

数据结构课程设计- 算术表达式求值

数据结构课程设计- 算术表达式求值

课程设计报告课程名称数据结构课程设计题目算术表达式求值指导教师设计起始日期 4.18~4.25学院计算机学院系别计算机科学与工程学生姓名班级/学号成绩一、需求分析设计一个算术表达式四则运算的程序,要求完成包括加、减、乘、除运算,包含括号的基本整数表达式的运算。

在这里运算数可以1位长度,也可以多位长度。

在运算之后输出的正确运算结果,输入表达式后演示在求值中运算数栈内的栈顶数据变化过程,最后得到运算结果。

(1)输入:3*(7-2)(2)输出:数据栈栈顶元素:3,7,2,7,5,3,15结果:15(3)自选数据二、概要设计1、使用栈的数据结构表示数据的存储。

2、设计算法将中缀表达式转换成后缀表达式,用栈的数据结构实现表达式的运算。

3、把中缀表达式转换为后缀表达式算法的基本思路是从头到尾地扫描中缀表达式中的每个字符,对于不同类型的字符按不情况进行处理。

三、详细设计数据结构:字符类型栈/* 定义字符类型栈*/typedef struct{char stackname[20];char *base;char *top;} Stack;算法:将中缀表达式转换为后缀表达式void Change(char* s1, char* s2)// 将字符串s1中的中缀表达式转换为存于字符串s2中的后缀表达式{Stack R; // 定义用于暂存运算符的栈InitStack(R); // 初始化栈Push(R,'#'); // 给栈底放入’#’字符,它具有最低优先级0int i,j;i=0; // 用于指示扫描s1串中字符的位置,初值为0j=0; // 用于指示s2串中待存字符的位置,初值为0char ch=s1[i]; // ch保存s1串中扫描到的字符,初值为第一个字符while( ch!='#'){ // 顺序处理中缀表达式中的每个字符if(ch==' ')// 对于空格字符不做任何处理,顺序读取下一个字符ch=s1[++i];else if(ch=='('){ // 对于左括号,直接进栈Push(R,ch);ch=s1[++i];}else if(ch==')'){ // 对于右括号,使括号内的仍停留在栈中的运算符依次// 出栈并写入到s2中while(Peek(R)!='(')s2[j++]=Pop(R);Pop(R); // 删除栈顶的左括号ch=s1[++i];}else if(ch=='+'||ch=='-'||ch=='*'||ch=='/'){ // 对于四则运算符,使暂存在栈中的不低于ch优先级// 的运算符依次出栈并写入到s2中char w=Peek(R);while(Precedence(w)>=Precedence(ch)){ // Precedence(w)函数返回运算符形参的优先级s2[j++]=w;Pop(R); w=Peek(R); }}四、调试分析调试:在设计过程中出现程序不能运行,发现不能找到结束标识符,因此在设计的时候需要人为动态添加结束标识符‘#’,顺利运行算法时间和空间分析:算法的运行时间主要花在while循环上,它从头到尾扫描后缀表达式中的每一个数据(每个操作数或运算符均为一个数据),若后缀表达式由n个数据组成,则此算法的时间复杂度为O(n)。

数据结构课程设计-算术表达式求值的实现

数据结构课程设计-算术表达式求值的实现

课程设计报告课程设计名称:数据结构课程设计课程设计题目:算术表达式求值的实现院(系):*****专业:*****班级:*****学号:*****姓名:*****指导教师:*****目录1 课程设计介绍 (1)1.1课程设计内容 (1)1.2课程设计要求 (1)2 课程设计原理 (2)2.1课设题目粗略分析 (2)2.2原理图介绍 (2)2.2.1 功能模块图 (2)2.2.2 流程图分析 (3)3 数据结构分析 (5)3.1存储结构 (5)3.2算法描述 (5)4 调试与分析 (7)4.1调试过程 (7)4.2程序执行过程 (7)参考文献 (8)附录(关键部分程序清单) (9)1 课程设计介绍1.1 课程设计内容编写算法能够进行整型和实型数的表达式求值,能够根据运算的数据选择正确的运算结果的数据类型,表达式的运算符为:+,—,*,/,(,),且括号可以嵌套。

1.2 课程设计要求1.给出必要的输入、输出信息和提示信息。

2.参考相应的资料,独立完成课程设计任务。

3.交规范课程设计报告和软件代码。

2 课程设计原理2.1 课设题目粗略分析根据课设题目要求,拟将整体程序分为三大模块。

此三个模块相互独立,没有嵌套调用的情况,以下是三个模块的大体分析:1.首先依次定义字符类型栈、整型栈、运算符栈和操作数栈,构造运算符栈和操作数栈,然后运算符、操作数依次入栈。

2. 依次读入表达式,若是操作符即进OPND栈,若是运算符即进OPTR栈。

顺序栈的存储结构是利用一组连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置,base为栈底指针,在顺序栈中,它始终指向栈底,即top=base可作为栈空的标记,每当插入新的栈顶元素时,指针top增1,删除栈顶元素时,指针top减1。

3. 按照运算符的优先级别对表达式进行求值运算。

2.2 原理图介绍该功能模块图介绍了这个程序的主要功能。

2.2.1 功能模块图图2.1功能模块图如图2.1所示,要实现表达式的求值,即必须要实现存储、读取和计算三项功能。

数据结构课程设计报告-表达式求值

数据结构课程设计报告-表达式求值

《数据结构》课程设计利用栈求表达式的值班级: 2学号: 100171021330姓名:吴迪指导老师:王方利用栈求表达式的值1、设计思路这个程序的关键是对数字与运算符的判断和运算符优先级的判断,以及出栈的运算。

建立两个栈,分别存储数字与运算符,栈1存运算符,栈2存数字。

依次读取表达式的字符串,先判断是数字还是运算符,如果是数字不能马上压入栈2,因为可能是大于10的数字,应该继续循环,如果还是数字,则利用计算保存数值,直到指到运算符时停止,将计算后的数字压入栈2。

压入运算符之前先将要压入的与栈顶的运算符优先级相比较,如果栈顶是‘(’而当前不是‘)’,则不需比较优先级,直接压入;如果栈顶是‘(’,当前是‘)’,则抵消(弹出‘(’,指向表达式下一个字符);若当前的运算符优先级大于栈顶的,则压入;若当前的运算符优先级小于栈內时,弹出栈顶的运算符,同时弹出两组数字,经过运算符的运算后再重新压到栈内。

为了方便判断运算结束,在存储运算符之前先将‘#’压入栈1中,在输入表达式时以‚#‛结束,所以可以以运算符==‘#’并且栈1顶==‘#’来结束运算,弹出栈2的数值,即为表达式求值的最终结果。

上述操作的算法步骤:(1)初始化算符S1,数字栈S2;,将‘#’压入算符栈S1中。

(2)读表达式字符=>w。

(3)当栈顶为‘#’并且w也是‘#’时结束;否则循环做下列步骤:(3-1)如果w是数字,存储到m,再经过计算存储到num中。

m=w-‘0’;num=num*pow(10,n)+m;n++;读下一个字符=>w,如果是运算符,则跳出循环;转3-2。

(3-2)w若是运算符,则:(3-2-1)如果栈顶为‘(’并且w为‘)’则‘(’出栈,读下一个字符=>w;转(3)。

(3-2-2)如果栈顶为‘(’或者栈顶优先级小于w优先级,则w入栈,读下一个字符=>w;转(3)。

否则:从算符栈中出栈,并从数字栈中弹出两组数字进行运算,将结果重新压入数字栈,转(3)。

数据结构课程设计-表达式求值【完整版】

数据结构课程设计-表达式求值【完整版】

XXXXXX大学《数据结构》课程设计报告班级:学号:姓名:指导老师:目录一算术表达式求值一、需求分析二、程序得主要功能三、程序运行平台四、数据结构五、算法及时间复杂度六、测试用例七、程序源代码二感想体会与总结算术表达式求值一、需求分析一个算术表达式就是由操作数(operand)、运算符(operator)与界限符(delimiter)组成得。

假设操作数就是正整数,运算符只含加减乘除等四种运算符,界限符有左右括号与表达式起始、结束符“#”,如:#(7+15)*(23—28/4)#。

引入表达式起始、结束符就是为了方便.编程利用“算符优先法”求算术表达式得值.二、程序得主要功能(1)从键盘读入一个合法得算术表达式,输出正确得结果。

(2)显示输入序列与栈得变化过程。

三、程序运行平台Visual C++6、0版本四、数据结构本程序得数据结构为栈。

(1)运算符栈部分:struct SqStack //定义栈{char *base; //栈底指针char *top; //栈顶指针intstacksize; //栈得长度};intInitStack (SqStack &s) //建立一个空栈S{if (!(s、base= (char *)malloc(50*sizeof(char))))exit(0);s、top=s、base;s、stacksize=50;return OK;}char GetTop(SqStack s,char &e) //运算符取栈顶元素{if (s、top==s、base) //栈为空得时候返回ERROR{ﻩ printf("运算符栈为空!\n");ﻩ return ERROR;}elsee=*(s、top-1); //栈不为空得时候用e做返回值,返回S得栈顶元素,并返回OK returnOK;}int Push(SqStack&s,char e) //运算符入栈{if (s、top—s、base >= s、stacksize)ﻩ{printf("运算符栈满!\n");ﻩs、base=(char*)realloc(s、base,(s、stacksize+5)*sizeof(char));//栈满得时候,追加5个存储空间if(!s、base)exit (OVERFLOW);s、top=s、base+s、stacksize;s、stacksize+=5;}ﻩ*(s、top)++=e;//把e入栈ﻩreturn OK;}int Pop(SqStack &s,char &e) //运算符出栈{if (s、top==s、base) //栈为空栈得时候,返回ERROR{printf("运算符栈为空!\n”);ﻩ return ERROR;}else{ﻩﻩe=*-—s、top;//栈不为空得时候用e做返回值,删除S得栈顶元素,并返回OK return OK;}}int StackTraverse(SqStack&s)//运算符栈得遍历{ﻩchar *t;ﻩt=s、base;ﻩif (s、top==s、base){ﻩ printf(”运算符栈为空!\n”); //栈为空栈得时候返回ERRORreturn ERROR;}while(t!=s、top){ﻩﻩprintf(" %c",*t); //栈不为空得时候依次取出栈内元素t++;ﻩ}return ERROR;}(2)数字栈部分:struct SqStackn//定义数栈{int *base; //栈底指针int*top; //栈顶指针int stacksize; //栈得长度};intInitStackn (SqStackn &s) //建立一个空栈S{s、base=(int*)malloc(50*sizeof(int));if(!s、base)exit(OVERFLOW);//存储分配失败s、top=s、base;s、stacksize=50;return OK;}int GetTopn(SqStackn s,int&e) //数栈取栈顶元素{if(s、top==s、base){printf("运算数栈为空!\n");//栈为空得时候返回ERRORﻩ return ERROR;}elseﻩe=*(s、top-1);//栈不为空得时候,用e作返回值,返回S得栈顶元素,并返回OKreturnOK;}int Pushn(SqStackn &s,int e) //数栈入栈{if(s、top—s、base>=s、stacksize){ﻩﻩprintf("运算数栈满!\n");//栈满得时候,追加5个存储空间ﻩs、base=(int*)realloc (s、base,(s、stacksize+5)*sizeof(int));if(!s、base) exit (OVERFLOW);ﻩs、top=s、base+s、stacksize;//插入元素e为新得栈顶元素s、stacksize+=5;}*(s、top)++=e; //栈顶指针变化returnOK;}int Popn(SqStackn &s,int &e)//数栈出栈{ﻩif (s、top==s、base){ﻩ printf("运算符栈为空!\n");//栈为空栈得视时候,返回ERRORﻩ return ERROR;ﻩ}else{ﻩﻩe=*—-s、top;//栈不空得时候,则删除S得栈顶元素,用e返回其值,并返回OK ﻩreturnOK;}}int StackTraversen(SqStackn &s)//数栈遍历{ﻩint*t;ﻩt=s、base ;ﻩif(s、top==s、base)ﻩ{printf("运算数栈为空!\n”);//栈为空栈得时候返回ERRORﻩ return ERROR;ﻩ}ﻩwhile(t!=s、top)ﻩ{printf(” %d”,*t); //栈不为空得时候依次输出t++;}return ERROR;}五、算法及时间复杂度1、算法:建立两个不同类型得空栈,先把一个‘#’压入运算符栈。

数据结构课程设计之算术表达式求值

数据结构课程设计之算术表达式求值

1【实验题目及要求】[问题描述]一个算术表达式是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。

假设操作数是正实数,运算符只含加减乘除等四种运算符,界限符有左右括号和表达式起始、结束符“#”,如:#(7+15)*(23-28/4)#。

引入表达式起始、结束符是为了方便。

编程利用“算符优先法”求算术表达式的值。

[基本要求](1)从键盘或文件读入一个合法的算术表达式,输出正确的结果。

(2)显示输入序列和栈的变化过程。

(3)考虑算法的健壮性,当表达式错误时,要给出错误原因的提示。

(4) 实现非整数的处理(可选功能)。

2【源代码(C语言)】#include<stdio.h>#include<stdlib.h>#include<string.h>#define MAXSIZE 20#define OK 1#define ERROR 0#define OVERLOW 0#define YES 1#define NO 0typedefstruct{char * base;char * top;int stacksize; //最大存储量}OPTR; //字符存储栈typedefstruct{float *base;float *top;int stacksize; //最大存储量}OPND; //数值存储栈int InitOptrStack(OPTR *); //字符栈初始化函数int OptrPush(OPTR *, char); //进字符栈操作int OptrPop(OPTR*, char *); //出字符栈操作int OptrEmpty(OPTR ); //判断字符栈是否为空char GetOptrTop(OPTR); //返回字符栈顶元素int InitOpndStack(OPND *); //数值栈初始化函数int OpndPush(OPND *, float); //进数值栈操作int OpndPop(OPND*, float*); //出数值栈操作int OpndEmpty(OPND ); //判断数值栈是否为空int JudgeChar(char); //判断是否为字符float GetFloat(char *); //接收一个数字char Precede(char, char); //判断优先级操作float Caculate(float,float,char);//计算数值{char ch, noMean, ci;float num, number1, number2;OPTR optr;OPND opnd;//system("color 30");InitOptrStack(&optr);InitOpndStack(&opnd);while(1){printf(" 请输入表达式以“#”开始,以“#”结束\n ");do{ch = getchar();}while(ch !='#'); //忽略前面非‘#’字符OptrPush(&optr, ch);ch = getchar();while(ch != '#' || GetOptrTop(optr) != '#'){if(!JudgeChar(ch)){ //如果输入的是数字num = GetFloat( &ch );OpndPush(&opnd, num);else{ //输入的是字符switch(Precede(GetOptrTop(optr),ch)){case'<':OptrPush(&optr,ch); //栈顶优先级低ch = getchar();break;case'=':OptrPop(&optr,&noMean); //左右括号,把左括号出栈ch = getchar ();break;case'>': //栈顶优先级高if(OpndPop(&opnd, &number2) && OpndPop(&opnd,&number1)){OptrPop(&optr, &ci);num = Caculate(number1, number2, ci ); //出栈计算OpndPush(&opnd, num);}else{printf(" 输入过多运算符!\n");system ("PAUSE");exit(0);}break;}//witch}//else}if(opnd.top -opnd.base >= 2){printf(" 俩个括号之间缺少运算符!\n ");system ("PAUSE");exit( 0 );}OpndPop(&opnd,&num); //直接把OPND的栈元素赋值给numprintf(" 运算结果为%.3f\n", num);}system ("PAUSE");}int InitOptrStack(OPTR * OP){OP->base = (char*)malloc((MAXSIZE+1)*sizeof(char));OP->top = OP->base;OP->stacksize = MAXSIZE;return OK;}int OptrPush(OPTR *OP, char ch){*(OP->top) = ch;OP->top++;return OK;}int OptrPop(OPTR *OP, char *ch){if(OP->base == OP->top)return ERROR;else{OP->top--;*ch = *(OP->top);return OK;}}int OptrEmpty(OPTR OP){if(OP.top == OP.base )return YES;elsereturn NO;}char GetOptrTop(OPTR OP){return *(OP.top -1);}int InitOpndStack(OPND * OP){if(!(OP->base = (float*)malloc((MAXSIZE+1)*sizeof(float)))) exit(OVERLOW);OP->top = OP->base;OP->stacksize = MAXSIZE;return OK;}int OpndPush(OPND *OP, float number) {*(OP->top) = number;OP->top++;return OK;}int OpndPop(OPND *OP, float* number) {if(OP->top == OP->base)return ERROR;else{OP->top--;*number = *(OP->top);return OK;}}int OpndEmpty(OPND OP){if(OP.top == OP.base )return YES;elsereturn NO;}int JudgeChar(char ch){if(ch>='0'&&ch<= '9')return NO;elsereturn YES;}float GetFloat(char* ch){int i;float num = 0;for( i = 0; *ch>= '0'&& *ch<= '9'; i++){ num = num*10 + *ch - '0';*ch = getchar();}return num;}char Precede(char a, char b){char ch;switch(a){case'+':case'-': if(b == '*' || b == '/' || b == '(')ch = '<';elsech = '>';break;case'*':case'/': if( b == '(')ch = '<';elsech = '>';break;case'(': if(b == ')')ch = '=';elseif(b == '#'){printf(" 缺少反括号\n");system ("PAUSE");exit(0);}elsech = '<';break;case')': if(b == '('){printf(" 两个括号之间没有符号相连!\n");system("PAUSE");exit(0);}ch = '>';break;case'#': if(b == '#')ch = '=';elseif(b == ')'){printf(" 没有左括号!\n ");system("PAUSE");exit(0);}elsech = '<';break;default: printf(" 输入运算符超出范围! \n ");system ("PAUSE");exit(0);break;}return ch;}float Caculate(float number1, float number2, char ci){float num;switch( ci){case'+': num = number1 + number2; break;case'-': num = number1 - number2; break;case'*': num = number1 * number2; break;case'/': num = number1 / number2; break;}return num;}3【算法思想】根据栈的原理,建立数字栈OPND和运算符号栈OPTR,对读入的字符进行判断,存入不同的栈内,每次读入一个字符就把该字符和运算符栈顶的优先级进行比较,然后选择相应的操作,这是这个程序的核心代码,如下:switch(Precede(GetOptrTop(optr),ch)){case '<':OptrPush(&optr,ch); //栈顶优先级低ch = getchar();break;case '=':OptrPop(&optr,&noMean); //左右括号,把左括号出栈ch = getchar ();break;case '>': //栈顶优先级高if(OpndPop(&opnd, &number2) && OpndPop(&opnd, &number1)){OptrPop(&optr, &ci);num = Caculate(number1, number2, ci ); //出栈计算OpndPush(&opnd, num);}else{printf(" 输入过多运算符!\n");system ("PAUSE");exit(0);}break;}//witch4【实现效果】完全可以实现题目的要求,除了下图的错误提示,本程序还可以提示的错误有:输入过多运算符,缺少反括号,两个括号之间缺少运算符相连,缺少左括号,输入的运算符超出范围等提示。

数据结构课程设计-表达式求值问题

数据结构课程设计-表达式求值问题

实验表达式求值问题1. 问题描述表达式是数据运算的基本形式。

人们的书写习惯是中缀式,如:11+22* (7-4 )/3. 中缀式的计算按运算符的优先级及括号优先的原则,相同级别从左到右进行计算。

表达式还有后缀表达式(如:11 22 7 4 - * 3 / + )和前缀表达式(+ 11 / * 22 - 7 4 3 )。

后缀表达式和前缀表达式中没有括号,给计算带来方便。

如后缀表达式计算时按运算符出现的先后进行计算。

本设计的主要任务是进行表达式形式的转换及不同形式的表达式计算。

2. 数据结构设计1)顺序栈类定义:首先应在类中定义成员函数,以此来完成顺序栈的相关操作,如下:class SqStackprivate:T *base; // 栈底指针int top; // 栈顶int stacksize; // 栈容量public:SqStack(int m); // 构建函数~SqStack(){delete [] base;top=0;stacksize=0;} // 析构函数void Push(T x); // 入栈T Pop(); // 出栈T GetTop(); // 获取栈顶元素int StackEmpty(); // 测栈空void ClearStack(); // 清空栈void StackTop(); // 返回栈顶指针void StackTranverse(); // 显示栈中元素};2)顺序栈类实现:对顺序栈进行初始化,初始化的首要操作就是创建一个空顺序栈。

Step1 :申请一组连续的内存空间为顺序栈使用:base=new T[m];i f(base==NULL)cout<<" 栈创建失败,退出!"<<endl; exit(1);}{Step2 :给栈顶、栈容量赋相应的值:stacksize=m;t op=-1;(2)顺序栈入栈:入栈需要在栈顶插入一个新元素并相应的调整栈顶。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验表达式求值问题1.问题描述表达式是数据运算的基本形式。

人们的书写习惯是中缀式,如:11+22*(7-4)/3.中缀式的计算按运算符的优先级及括号优先的原则,相同级别从左到右进行计算。

表达式还有后缀表达式(如:11 22 7 4 - * 3 / +)和前缀表达式(+ 11 / * 22 - 7 4 3)。

后缀表达式和前缀表达式中没有括号,给计算带来方便。

如后缀表达式计算时按运算符出现的先后进行计算。

本设计的主要任务是进行表达式形式的转换及不同形式的表达式计算。

2.数据结构设计(1)顺序栈类定义:首先应在类中定义成员函数,以此来完成顺序栈的相关操作,如下: class SqStack{private:T *base; //栈底指针int top; //栈顶int stacksize; //栈容量public:SqStack(int m); //构建函数~SqStack(){delete [] base;top=0;stacksize=0;} //析构函数void Push(T x); //入栈T Pop(); //出栈T GetTop(); //获取栈顶元素int StackEmpty(); //测栈空void ClearStack(); //清空栈void StackTop(); //返回栈顶指针void StackTranverse(); //显示栈中元素};(2)顺序栈类实现:对顺序栈进行初始化,初始化的首要操作就是创建一个空顺序栈。

Step1:申请一组连续的内存空间为顺序栈使用:base=new T[m];i f(base==NULL){cout<<"栈创建失败,退出!"<<endl;exit(1);}Step2:给栈顶、栈容量赋相应的值:stacksize=m;t op=-1;(2)顺序栈入栈:入栈需要在栈顶插入一个新元素并相应的调整栈顶。

Step1:首先判断是否栈满,如果栈满,抛出“上溢”信息,无法入栈,否则转入Step2;if(top==stacksize-1) throw "栈满,无法入栈";Step2:栈顶指针增加1;top++;Step3:新元素插入栈顶位置;base[top]=x;(3)顺序栈出栈:出栈需要取出栈顶元素,并相应的调整栈顶指针。

Step1:首先判断是否栈空,如果栈空,抛出“下溢”信息,无法出栈,否则转入Step2;i f(top==-1) throw "栈空,不能出栈";Step2:取出栈顶元素,栈顶指针减1;T x;x=base[top--];Step3:返回栈顶元素;return x;(4)顺序栈取栈顶元素:取栈顶元素是取出栈顶元素的值,但不改变栈。

Step1:首先判断是否栈空,如果栈空,抛出“下溢”信息,无法出栈,否则转入Step2;if(top==-1) throw "栈空,栈顶无元素";Step2:取出栈顶元素,返回栈顶元素;return base[top];(5)判断栈空:判断是否栈空,返回Step1:如果栈空,返回1,否则转Step2;if(top==-1)return 1;Step2:否则返回0;return 0;(6)清空栈:将栈清空。

top=-1(7)返回栈顶指针:cout<<"栈顶top= "<<top;(8)输出栈元素:将栈顶指向i,从栈顶输出到栈底。

Step1:将栈顶指针赋予i;int i=top;Step2:如果栈不为空,则输出;while(i>=0)cout<<base[i--]<<'\t';cout<<endl;3.算法设计本实验要求读入中缀表达式,求中缀表达式,将中缀表达式转换成前,后缀表达式,利用前,中,后缀表达式求值,并且能够输出等等操作,这就需要构建相关算法。

(1)首先要将表达式中操作符优先级进行排序,优先级从高到低依次为(,),*,/,+,-,算法如下,利用选择语句比较:char Precede(char t1,char t2){//运算符的优先级比较char f;switch(t2){case '+':case '-':if(t1=='('||t1=='=')f='<';elsef='>';break;case '*':case '/':if(t1=='*'||t1=='/'||t1==')')f='>';elsef='<';break;case '(':if(t1==')'){cout<<"ERROR1"<<endl;exit(0);}elsef='<';break;case ')':switch(t1){case '(':f='=';break;case '=':cout<<"ERROR2"<<endl;exit(0);default: f='>';}break;case '=':switch(t1){case '=':f='=';break;case '(':cout<<"ERROR2"<<endl;exit(0);default: f='>';}}return f;}(2)其次,就是判断输入元素是否为运算符,若为运算符,就输出1,否则输出0; int In(char c){ // 判断c是否为运算符switch(c){case'+':case'-':case'*':case'/':case'(':case')':case'=':return 1;default:return 0;}}(3)构造表达式的运算算法,利用选择语句将运算分类:float Operate(float a,char theta,float b){//实施一次运算float c;switch(theta){case'+':c=a+b;break;case'-':c=a-b;break;case'*':c=a*b;break;case'/':c=a/b;}return c;}(4)要求一:中缀表达式求值Step1:首先需要将运算符和运算数分开存放,这就需要分别创建栈:SqStack<char> OP(20);SqStack<float> OD(20);Step2:创建相关字符来存放由键盘输入的字符,并以“=”键结束char theta;float a,b,d;char c,x; // 存放由键盘接收的字符char z[6]; // 存放符点数字符串int i;OP.Push('=');Step3:当输入为数字元素是,直接存入表达式栈就可以,而当输入是符号元素时,就需要判断优先级并进行存栈出栈操作,如果是非法字符,输出错误,并且不存入;c=*exp++;x=OP.GetTop();while(c!='='||x!='='){if(In(c)) // 是7种运算符之一switch(Precede(x,c)){case'<':OP.Push(c); // 栈顶元素优先权低c=*exp++;break;case'=':x=OP.Pop(); // 脱括号并接收下一字符c=*exp++;break;case'>':theta=OP.Pop(); // 退栈并将运算结果入栈 b=OD.Pop();a=OD.Pop();OD.Push(Operate(a,theta,b));}else if(c>='0'&&c<='9'||c=='.') // c是操作数{i=0;do{z[i]=c;i++;c=*exp++;}while(c>='0'&&c<='9'||c=='.');z[i]='\0';d=atof(z); // 将字符串数组转为符点型存于dOD.Push(d);}else // c是非法字符{cout<<"ERROR3"<<endl;;exit(0);}x=OP.GetTop();}d=OD.GetTop();return d;}(4)中缀表达式转换成后缀表达式:Step1:创建一个操作符栈;char c,x;int i=0;SqStack<char> OP(20);Step2:从左到右扫描读取表达式,执行下列运算,直至表达式结束符。

SqStack<char> OP(20);OP.Push('='); // =是表达式结束标志cout<<"exp:"<<exp<<endl;c=*exp++;2.1:如果是操作数,输出;if((c>='0'&&c<='9')||c=='.'){postexp[i++]=c;c=*exp++;}2.2:如果是操作符A2,把操作符栈栈顶的操作符A2与它比较:2.2.1:A1<A2,A2如操作符栈。

2.2.2:A1=A2,从操作符栈退出一个操作符,不输出。

2.2.3:A1>A2,从操作符栈输出所有比A2优先级高的运算符,直至栈顶算符优先级小于A2,A2如操作符栈。

if(In(c)) // 是7种运算符之一{postexp[i++]=' ';x=OP.GetTop();switch(Precede(x,c)){case'<':OP.Push(c); // 栈顶元素优先权低c=*exp++;break;case'=':x=OP.Pop(); // 脱括号并接收下一字符c=*exp++;break;case'>':postexp[i++]=OP.Pop(); // 运算符出栈输出break;}}postexp[i]='\0';(4)中缀表达式转换成前缀表达式:Step1:创建一个操作符栈;char c,x;int i=0;SqStack<char> OP(20);Step2:从右到左扫描读取表达式,执行下列运算,直至表达式结束符;while(*exp != '\0')*exp++;O P.Push('='); // =是表达式结束标志c=*exp--;2.1:如果是操作数,输出;if((c>='0'&&c<='9')||c=='.'){preexp[i++]=c;c=*exp--;}2.2:如果是操作符A2,把操作符栈栈顶的操作符A2与它比较:2.2.1:A1<A2,A2如操作符栈。

相关文档
最新文档