算术表达式求值
数据结构表达式求值实验报告

竭诚为您提供优质文档/双击可除数据结构表达式求值实验报告篇一:数据结构实验二——算术表达式求值实验报告《数据结构与数据库》实验报告实验题目算术表达式求值学院:化学与材料科学学院专业班级:09级材料科学与工程系pb0920603姓学邮名:李维谷号:pb09206285箱:指导教师:贾伯琪实验时间:20XX年10月10日一、需要分析问题描述:表达式计算是实现程序设计语言的基本问题之一,它的实现是栈的应用的一个典型例子。
设计一个程序,演示通过将数学表达式字符串转化为后缀表达式,并通过后缀表达式结合栈的应用实现对算术表达式进行四则混合运算。
问题分析:在计算机中,算术表达式由常量、变量、运算符和括号组成。
由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行。
因而在程序设计时,借助栈实现。
设置运算符栈(字符型)和运算数栈(浮点型)辅助分析算符优先关系。
在读入表达式的字符序列的同时完成运算符和运算数的识别处理,然后进行运算数的数值转换在进行四则运算。
在运算之后输出正确运算结果,输入表达式后演示在求值中运算数栈内的栈顶数据变化过程,最后得到运算结果。
算法规定:输入形式:一个(:数据结构表达式求值实验报告)算术表达式,由常量、变量、运算符和括号组成(以字符串形式输入)。
为使实验更完善,允许操作数为实数,操作符为(、)、.(表示小数点)、+、-、*、/、^(表示乘方),用#表示结束。
输出形式:演示表达式运算的中间结果和整个表达式的最终结果,以浮点型输出。
程序功能:对实数内的加减乘除乘方运算能正确的运算出结果,并能正确对错误输入和无定义的运算报错,能连续测试多组数据。
测试数据:正确输入:12*(3.6/3+4^2-1)#输出结果:194.4无定义运算:12*(3.6/(2^2-4)+1)#输出结果:表达式出错,除数为0,无意义错误输入:12+s#输出结果:eRRoR!二、概要设计拟采用两种类型的展分别对操作数和操作符进行操作。
数据结构算术表达式求值实验

北京理工大学珠海学院《数据结构》课程设计报告题目:____________算术表达式求值_________________所在学院:专业班级:学生姓名:指导教师:2010年 05 月 26 日目录1.前言 (1)2.概要设计 (1)2。
1 数据结构设计 (1)2.2 算法设计 (1)2。
3 ADT描述 (2)2.4 功能模块分析 (2)3.详细设计 (3)3.1 数据存储结构设计 (3)3.2主要算法流程图(或算法伪代码) (3)4.软件测试 (6)5.心得体会 (8)参考文献 (8)附录 (8)1.前言在计算机中,算术表达式由常量、变量、运算符和括号组成。
由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行。
因而在程序设计时,借助栈实现。
算法输入:一个算术表达式,由常量、变量、运算符和括号组成(以字符串形式输入)。
为简化,规定操作数只能为正整数,操作符为+、—*、/,用#表示结束。
算法输出:表达式运算结果.算法要点:设置运算符栈和运算数栈辅助分析算符优先关系。
在读入表达式的字符序列的同时,完成运算符和运算数的识别处理,以及相应运算。
2.概要设计2。
1 数据结构设计任何一个表达式都是由操作符,运算符和界限符组成的.我们分别用顺序栈来寄存表达式的操作数和运算符.栈是限定于紧仅在表尾进行插入或删除操作的线性表。
顺序栈的存储结构是利用一组连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置,base为栈底指针,在顺序栈中,它始终指向栈底,即top=base可作为栈空的标记,每当插入新的栈顶元素时,指针top增1,删除栈顶元素时,指针top减1。
2.2 算法设计为了实现算符优先算法。
可以使用两个工作栈。
一个称为OPTR,用以寄存运算符,另一个称做OPND,用以寄存操作数或运算结果.1。
首先置操作数栈为空栈,表达式起始符”#"为运算符栈的栈底元素;2.依次读入表达式,若是操作符即进OPND栈,若是运算符则和OPTR栈的栈顶运算符比较优先权后作相应的操作,直至整个表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为”#”)。
数据结构-算术表达式求值(含需求分析和源代码)

需求分析(附代码)一、需求分析(1)首先定义两个栈OPTR、OPND,栈OPTR用于存放运算符,栈OPND 用于存放操作数;定义一个一维数组expr【】存放表达式串。
(2)主函数主要包括两部分:(1)判断运算符优先权,返回优先权高的;(2)操作函数。
(3)开始将‘#’入操作符栈,通过一个函数来判别算术运算符的优先级。
且规定‘#’的优先级最低。
在输入表达式的最后输入‘#’,代表表达式输入结束。
在表达式输入过程中,遇操作数则直接入栈。
遇到运算符则与栈顶运算符比较优先级,当前运算符优先级高(前面的运算还不应执行)则当前运算符入栈,扫描下一符号;否则栈顶运算符出栈,两操作数出栈,进行运算,所得结果入数栈,重新比较当前运算符(注意当前运算符未变)与新栈顶运算符。
如此重复直到栈顶运算符与当前符号均为‘#’,运算结束。
(4)最初实现的加、减、乘、除及带小括号的基本运算,但考虑到实用性,后来的设计中有加上了乘方运算。
在乘方运算中借用了C库中自带的乘方函数pow。
二、概要设计1、设定栈的抽象数据类型定义:ADT Stack {数据对象:D={ ai | ai∈ElemSet, i=1,2,...,n,n≥0 }数据关系:R1={ <ai-1, ai >| ai-1, ai∈D, i=2,...,n }约定an端为栈顶,a1端为栈底。
基本操作:InitStack(&S)操作结果:构造一个空栈S。
DestroyStack(&S)初始条件:栈S已存在。
操作结果:栈S被销毁。
StackEmpty(S)初始条件:栈S已存在。
操作结果:若栈S为空栈,则返回TRUE,否则FALE。
StackLength(S)初始条件:栈S已存在。
操作结果:返回S的元素个数,即栈的长度。
GetTop(S, &e)初始条件:栈S已存在且非空。
操作结果:用e返回S的栈顶元素。
ClearStack(&S)初始条件:栈S已存在。
c语言算术表达式求值

c语言算术表达式求值C语言是一种广泛应用的编程语言,其强大的算术表达式求值功能使其在科学计算、数据处理、游戏开发等领域有着重要的应用。
本文将介绍C语言中算术表达式求值的相关知识,包括运算符、运算符优先级、表达式求值的顺序等内容。
我们需要了解C语言中常用的算术运算符。
C语言支持的算术运算符包括加法(+)、减法(-)、乘法(*)、除法(/)和求余(%)等。
这些运算符用于对数值进行基本的加减乘除运算。
在C语言中,运算符的优先级决定了表达式求值的顺序。
常见的运算符优先级从高到低依次为:1. 括号(()):括号中的表达式具有最高的优先级,可以改变默认的运算次序。
2. 一元运算符:包括正号(+)和负号(-),用于表示正负数。
3. 乘法、除法和求余:乘法(*)、除法(/)和求余(%)的优先级相同,从左到右依次计算。
4. 加法和减法:加法(+)和减法(-)的优先级相同,从左到右依次计算。
在使用C语言进行算术表达式求值时,我们需要遵循这些运算符的优先级规则,以保证表达式的正确求值。
如果表达式中包含多个运算符,我们需要根据优先级确定运算的顺序,可以使用括号来改变默认的运算次序。
下面我们将通过几个例子来说明C语言中算术表达式求值的过程。
例1:求解一个简单的算术表达式假设我们需要计算表达式 3 + 4 * 2,根据运算符优先级规则,先计算乘法,再计算加法。
具体的求解过程如下:1. 计算4 * 2,得到8。
2. 计算3 + 8,得到11。
所以,表达式3 + 4 * 2的值为11。
例2:使用括号改变运算次序假设我们需要计算表达式(3 + 4) * 2,根据运算符优先级规则,先计算括号内的加法,再计算乘法。
具体的求解过程如下:1. 计算3 + 4,得到7。
2. 计算7 * 2,得到14。
所以,表达式(3 + 4) * 2的值为14。
通过以上两个例子,我们可以看到,C语言中的算术表达式求值是按照运算符优先级和运算次序进行的,遵循从左到右的计算规则。
数据结构 算术表达式求值

/**************************************************************************** 2、算术表达式求值(必做) (栈)时间:2012年12月[问题描述]一个算术表达式是由操作数( operand)、运算符(operator )和界限符(delimiter)组成的。
假设操作数是正实数,运算符只含加减乘除等四种运算符,界限符有左右括号和表达式起始、结束符“# ”,如:#(7+15)*(23-28/4)#。
引入表达式起始、结束符是为了方便。
编程利用“算符优先法”求算术表达式的值。
[基本要求](1)从键盘或文件读入一个合法的算术表达式,输出正确的结果。
(2)显示输入序列和栈的变化过程。
(3)考虑算法的健壮性,当表达式错误时,要给出错误原因的提示。
***************************************************************************/ #include <stdio.h>#include <stdlib.h>#include <string.h>#define OVERFLOW 0#define ERROR 0#define OK 1#define STACK_INIT_SIZE 100 //存储空间初始分配量#define STACKINCREMENT 10 //存储空间分配增量#define MAXSIZE 100#define N 100//*********************************************************************** struct expression{double result;char expstr[MAXSIZE];}exp;typedef struct{char *base; //在栈构造之前和销毁之后,base的值为NULLchar *top; //操作符栈栈顶指针int stacksize; //当前已分配的存储空间,以元素为单位}StackOPTR;//操作符栈typedef struct{float *base; //在栈构造之前和销毁之后,base的值为NULLfloat *top; //操作数栈栈顶指针int stacksize; //当前已分配的存储空间,以元素为单位}StackOPND;//操作数栈//************************栈的基本操作************************************************//***初始化***void InitStack(StackOPTR &S)//操作符栈初始化{S.base=(char *)malloc(STACK_INIT_SIZE * sizeof(char));if(!S.base)exit(OVERFLOW);S.top=S.base;S.stacksize=STACK_INIT_SIZE;}void InitStack(StackOPND &S)//操作数栈初始化{S.base=(float *)malloc(STACK_INIT_SIZE * sizeof(float));if(!S.base)exit(OVERFLOW);S.top=S.base;S.stacksize=STACK_INIT_SIZE;}//***GetTop***int GetTop(StackOPTR S,char &e)//若操作符栈不空,则用e返回s的栈顶元素{if(S.top==S.base)return ERROR;e=*(S.top-1);return OK;}int GetTop(StackOPND S,float &e)//若操作数栈不空,则用e返回s的栈顶元素{if(S.top==S.base)return ERROR;e=*(S.top-1);return OK;}//***Push***void Push(StackOPTR &S,char e)//插入元素e为新的操作符栈顶元素{if(S.top-S.base>=S.stacksize){S.base=(char*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(char));if(!S.base)exit(OVERFLOW);S.top=S.base+S.stacksize;S.stacksize+=STACKINCREMENT;}*S.top++=e;}void Push(StackOPND &S,float e)//插入元素e为新的操作数栈顶元素{if(S.top-S.base>=S.stacksize){S.base=(float*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(float));if(!S.base)exit(OVERFLOW);S.top=S.base+S.stacksize;S.stacksize+=STACKINCREMENT;}*S.top++=e;}//***Pop***int Pop(StackOPTR &S,char &e)//若操作符栈不空,删除s的栈顶元素,用e返回其值{if(S.top==S.base)return ERROR;e=*--S.top;return OK;}int Pop(StackOPND &S,float &e)//若操作数栈不空,删除s的栈顶元素,用e返回其值{if(S.top==S.base)return ERROR;e=*--S.top;return OK;}#define OPSIZE 7//运算符个数char OP[OPSIZE]={'+','-','*','/','(',')','#'};//运算符集合// 表3.1 算符间的优先关系char Prior[7][7] ={'>','>','<','<','<','>','>','>','>','<','<','<','>','>','>','>','>','>','<','>','>','>','>','>','>','<','>','>','<','<','<','<','<','=',' ','>','>','>','>',' ','>','>','<','<','<','<','<',' ','='};//***int In(char c,char *OP)//OP是运算符集合,检验是否为运算符{bool check=false;for(int i=0;i<OPSIZE;i++){if(c==OP[i])check=true;}return check;}//***float Operate(float a,char theta,float b)//进行二元运算aeb {switch(theta){case'+':return a+b;break;case'-':return a-b;break;case'*':return a*b;break;case'/':if(b==0){printf("不得出现0作为除数!\n");return 0;}elsereturn a/b;break;default:return 0;}}//***int Xu_Op(char theta,char *OP)//返回运算符c在OP中的序号{int i;for(i=0;i<OPSIZE;i++){if(theta==OP[i])return i;}return 0;}char Precede(char theta1,char theta2)//判断运算符栈的栈顶运算符theta1和读入的运算符theta2优先关系{return Prior[Xu_Op(theta1,OP)][Xu_Op(theta2,OP)];}//****算法健壮性的检查*******int change(char c)//字符都改成编号{switch(c){case'(': return 0;break;case'#': return 1;break;case')': return 2;break;case'+': return 3;break;case'-': return 3;break;case'*': return 4;break;case'/': return 4;break;case'0':case'1':case'2':case'3':case'4':case'5':case'6':case'7':case'8':case'9': return -1;break;default: return -2;}}int Wrong(char *exp)//检查算法的健壮性{char *p,*q;int i=0;//记录括号,i=0,合法。
c语言算术表达式求值

c语言算术表达式求值【实用版】目录1.引言2.C 语言算术表达式的基本概念3.C 语言算术表达式的求值方法4.实际应用示例5.总结正文【引言】在 C 语言编程中,算术表达式是用来进行数值计算的重要工具。
本篇文章将为大家介绍 C 语言算术表达式的求值方法。
【C 语言算术表达式的基本概念】C 语言中的算术表达式主要包括以下几种:1.一元运算符:例如+、-、*、/等,用于对一个数值进行操作。
2.二元运算符:例如+、-、*、/等,用于对两个数值进行操作。
3.关系运算符:例如<、>、<=、>=、==、!=等,用于比较两个数值的大小或相等性。
4.逻辑运算符:例如&&、||、! 等,用于进行逻辑判断。
【C 语言算术表达式的求值方法】C 语言中,算术表达式的求值主要遵循以下规则:1.先进行括号内的运算,再进行括号外的运算。
2.先进行乘除法运算,再进行加减法运算。
3.关系运算符和逻辑运算符的优先级较低,从左到右依次进行运算。
【实际应用示例】下面我们通过一个实际的 C 语言程序,来演示算术表达式的求值过程。
```c#include <stdio.h>int main() {int a = 10, b = 5;int result;result = a + b * (a - b) / (a * b);printf("The result is: %d", result);return 0;}```在这个程序中,我们定义了两个整数变量 a 和 b,并通过算术表达式计算 result 的值。
根据我们之前提到的算术表达式求值规则,我们可以将这个表达式分解为以下几个步骤:1.计算括号内的值:a - b = 10 - 5 = 52.计算乘法运算:b * (a - b) = 5 * 5 = 253.计算除法运算:(a * b) / (a * b) = 14.计算加法运算:a + 25 = 10 + 25 = 355.输出结果:printf("The result is: %d", result); 输出 35【总结】通过本篇文章的介绍,相信大家已经对 C 语言算术表达式的求值方法有了更加深入的了解。
C#算术表达式求值(后缀法),看这一篇就够了

C#算术表达式求值(后缀法),看这⼀篇就够了⼀、种类介绍算术表达式有三种:前缀表达式、中缀表达式和后缀表达式。
⼀般⽤的是中缀,⽐如1+1,前后缀就是把操作符移到前⾯和后⾯,下⾯简单介绍⼀下这三种表达式。
1、前缀表⽰法前缀表⽰法⼜叫波兰表⽰法,他的操作符置于操作数的前⾯(例:+ 1 2),是波兰数学家扬·武卡谢维奇1920年代引⼊的,⽤于简化命题逻辑。
因为我们⼀般认为操作符是在操作数中间的,所以在⽇常⽣活中⽤的不多,但在计算机科学领域占有⼀席之地。
⼀般的表⽰法对计算机来说处理很⿇烦,每个符号都要考虑优先级,还有括号这种会打乱优先级的存在,将使计算机花费⼤量的资源进⾏解析。
⽽前缀表⽰法没有优先级的概念,他是按顺序处理的。
举个例⼦:9-2*3这个式⼦,计算机需要先分析优先级,先乘后减,找到2*3,再进⾏减操作;化成前缀表⽰法就是:- 9 * 2 3,计算机可以依次读取,操作符作⽤于后⼀个操作数,遇到减就是让9减去后⾯的数,⽽跟着9的是乘,也就是说让9减去乘的结果,这对计算机来说很简单,按顺序来就⾏了。
2、中缀表⽰法这也就是我们⼀般的表⽰法,他的操作符置于操作数的中间(例:1 + 2),前⾯也说过这种⽅法不容易被计算机解析,但他符合⼈们的普遍⽤法,许多编程语⾔也就⽤这种⽅法了。
在中缀表⽰法中括号是必须有的,要不然运算顺序会乱掉。
3、后缀表⽰法后缀表⽰法⼜叫逆波兰表⽰法,他的操作符置于操作数的后⾯(例:1 2 +),他和前缀表⽰法都对计算机⽐较友好,但他很容易⽤堆栈解析,所以在计算机中⽤的很多。
他的解释过程⼀般是:操作数⼊栈;遇到操作符时,操作数出栈,求值,将结果⼊栈;当⼀遍后,栈顶就是表达式的值。
因此逆波兰表达式的求值使⽤堆栈结构很容易实现,且能很快求值。
注意:逆波兰记法并不是简单的波兰表达式的反转。
因为对于不满⾜交换律的操作符,它的操作数写法仍然是常规顺序,如,波兰记法/ 6 3的逆波兰记法是6 3 /⽽不是3 6 /;数字的数位写法也是常规顺序。
利用栈来实现算术表达式求值的算法

利用栈来实现算术表达式求值的算法利用栈来实现算术表达式求值的算法算术表达式是指按照一定规则组成的运算式,包含数字、运算符和括号。
在计算机中,求解算术表达式是一项基本的数学运算任务。
根据算术表达式的性质,我们可以考虑利用栈这一数据结构来实现求值算法。
一、算法思路首先,我们需要明确一个重要概念——逆波兰表达式(ReversePolish notation)。
逆波兰表达式是一种没有括号的算术表达式,其运算规则是先计算后面的数字和运算符,再计算前面的数字和运算符。
例如,对于算术表达式“3+4*5-6”,其对应的逆波兰表达式为“3 45 * +6 -”。
那么,我们可以利用栈来实现将中缀表达式转化为逆波兰表达式的过程,具体步骤如下:1. 创建两个栈——操作数栈和操作符栈。
2. 从左到右扫描中缀表达式的每一个数字和运算符,遇到数字则压入操作数栈中,遇到运算符则进行如下操作:(1)如果操作符栈为空或当前运算符的优先级大于栈顶运算符的优先级,则将当前运算符压入操作符栈中。
(2)如果当前运算符的优先级小于或等于栈顶运算符的优先级,则将栈顶运算符弹出并加入操作数栈中,重复此过程直到遇到优先级较低的运算符或操作符栈为空为止,然后将当前运算符压入操作符栈中。
3. 扫描完中缀表达式后,若操作符栈不为空,则将其中所有运算符弹出并加入操作数栈中。
4. 最终,操作数栈中存放的就是逆波兰表达式,我们可以按照逆波兰表达式的计算规则来计算其结果。
二、算法优点利用栈来实现算术表达式求值的算法具有以下优点:1. 代码简洁易懂,易于实现和维护。
2. 由于将中缀表达式转化为逆波兰表达式后,可以减少运算符的优先级关系而消除括号,从而减少求值的复杂度,提高程序的执行效率。
三、代码实现下面是利用栈来实现算术表达式求值的算法的Python代码实现:```pythonclass Stack:def __init__(self):self.items = []def push(self, item):self.items.append(item)def pop(self):return self.items.pop()def peek(self):return self.items[-1]def is_empty(self):return len(self.items) == 0def size(self):return len(self.items)def calculate(op_num1, op_num2, operator):if operator == "+":return op_num1 + op_num2elif operator == "-":return op_num1 - op_num2elif operator == "*":return op_num1 * op_num2elif operator == "/":return op_num1 / op_num2def infix_to_postfix(infix_expr):opstack = Stack()postfix_expr = []prec = {"+": 1, "-": 1, "*": 2, "/": 2, "(": 0} token_list = infix_expr.split()for token in token_list:if token.isdigit():postfix_expr.append(token)elif token == '(':opstack.push(token)elif token == ')':top_token = opstack.pop()while top_token != '(':postfix_expr.append(top_token)top_token = opstack.pop()else:while (not opstack.is_empty()) and(prec[opstack.peek()] >= prec[token]):postfix_expr.append(opstack.pop())opstack.push(token)while not opstack.is_empty():postfix_expr.append(opstack.pop())return " ".join(postfix_expr)def postfix_eval(postfix_expr):opstack = Stack()token_list = postfix_expr.split()for token in token_list:if token.isdigit():opstack.push(int(token))else:op_num2 = opstack.pop()op_num1 = opstack.pop()result = calculate(op_num1, op_num2, token) opstack.push(result)return opstack.pop()infix_expr = "3 + 4 * 5 - 6"postfix_expr = infix_to_postfix(infix_expr)print(postfix_expr)print(postfix_eval(postfix_expr))```四、总结算术表达式求值是一项常见的数学运算任务,利用栈这一数据结构来实现求值算法是一种简单有效的方法,它将中缀表达式转化为逆波兰表达式后,可以消除括号并减少运算符的优先级关系,从而提高程序的执行效率。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
题目:算术表达式求值问题内容:一个算术表达式是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。
假设操作数是正整数,运算符只含加减乘除等四种运算符,界限符有左右括号和表达式起始、结束符“#”,如:#(7+15)*(23-28/4)#。
引入表达式起始、结束符是为了方便。
编程利用“算符优先法”求算术表达式的值。
要求:(1)从键盘读入一个合法的算术表达式,输出正确的结果。
(2)显示输入序列和栈的变化过程。
选作内容:操作数类型扩充到实数。
一:问题分析和任务定义1.问题分析:分析题目并参考书目可以基本了解完成一个算术表达式所存在的问题。
对一个表达式来说,由于各种运算符和界限符的运用,运算符和界限符的优先级决定了算术表达式不是简单的从左往右的运算。
因此设计算法完成算术表达式时就要考虑各运算符和界限符的优先级,同时还要注意操作数与算符的判断。
在算法中要求完成操作数、运算符和界限符的出入栈,运算符和界限符的优先级比较和操作数之间的运算。
最后完成的算法要求输入一个算术表达式,能够正确的计算出来它的最后结果并输出。
为了不用考虑算符优先级,将输入的中缀表达式转换成后缀表达式。
这样就可以知道实现本程序需要进行的操作:1)建立空栈,存储信息;2)运用函数实现出入栈和取栈顶元素操作。
3)将中缀表达式转换成后缀表达式。
4)实现后缀表达式的求解。
5)建立一个函数使中缀表达式能够被有效输入。
本程序的关键是中缀表达式转换成后缀表达式对于栈的操作(1)建空栈setStack() 运算的结果是将栈顶元素返回。
(2)清空栈EmptyStack(),可以用于判断栈内元素的有无,在栈顶元素的输出被使用。
(3)入栈push(),出栈pop()和取栈顶元素top()。
2.任务定义1).本演示程序中,利用栈将输入的中缀表达式转换成后缀表达式,并完成其求解过程来达到计算表达式的目的。
2).演示程序以用户和计算机的对话方式执行,即在计算机终端上显示"提示信息"之后,由用户在键盘上输入演示程序中需要输入的数据,以“回车符”为结束标志。
相应的输入数据和运算结果显示在其后。
3).程序执行的命令包括:1)输入任意一个整数表达式;2)是否继续。
4).测试数据输入一个整数表达式:3+(5*8-9)输出:后缀表达式:3 5 8 *9 -+结果为:34继续?(y/n)二、数据结构的选择和概要设计算术表达式中各数据元素间存在一种线性关系,设计的数据类型如下:#define MAXNUM 50typedef int DataType;typedef struct {DataType s[MAXNUM];int t;}SeqStack,*PSeqStack;//定义一个类型名为SeqStack的数据类型本算法设计过程中只采用加减乘除等四种运算符,题目要求借助栈完成算法设计,提示中要把中缀表达式转换成后缀表达式计算,因此操作运算包括要建空栈、清空栈、进栈、出栈、取栈顶元素,中缀表达式转换成后缀表达式,后缀表达式的运算等。
将运算符和界限符一起描述为算符,本程序的设计如下:(1)先定义一下数据结构来存储算术表达式。
(2)建空栈setstack(),清空栈。
(3)对栈进行的运算函数,出入栈和取栈顶元素。
(4)中缀表达式转换成后缀表达式的函数its()。
(5)后缀表达式计算函数。
(6)设计存放后缀表达式的队列。
(7)主函数main(),使得整个程序完整进行。
三、详细设计和编码为了实现概要设计中的所有数据类型,对每个操作给出算法。
对主程序和其他模块也都需要写出算法。
1)数据类型#define MAXNUM 50typedef int DataType;typedef struct {DataType s[MAXNUM];int t;}SeqStack,*PSeqStack;//定义一个类型名为SeqStack的数据类型建空栈和其它关于栈的操作这部分为栈的运算问题。
为后面表达式转换和计算做准备。
这方面的知识书上有系统讲到,不需要过多去设计算法。
2)表达式的转换和计算将中缀表达式转换成后缀表达式,顺序扫描中缀算术表达式,当读到数字时直接将起送至输出队列中;当读到运算符时,将栈中所有优先级高于或等于该运算符的运算符弹出,送至输出队列中,再将当前运算符入栈;当读入左括号时,即入栈;当读入右括号时,将靠近栈的第一个左括号上面的运算符依次弹出,送至输出队列中,再删除栈中左括号。
在计算后缀表达式式,最后保存的值是最先取出参与运算,所以要用到栈。
读到数字时直接送至输出队列中:switch(c1) {case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':set =1;suffix[j++]=c1; /*遇到数字输出*/break;当读到左括号时入栈:case '(':set=0;push(ps, c1); /*遇到左括号,入栈*/break;当读入右括号时,将靠近栈的第一个左括号上面的运算符依次弹出,送至输出队列中,再删除栈中左括号:case ')':c2 = ')'; /*遇到右括号把右括号赋值给c2*/while(!EmptyStack(ps)) { /*当栈不为空时*/c2=top(ps); /*遇到右括号取栈顶*/pop(ps); /*出栈*/if(c2 =='(')break; /*遇到左括号时停止出栈*/suffix[j++]=c2; /*c2的值放入后缀表达式中*/}当读到加减乘除号时,栈和后缀表达式的变化。
因为优先级的关系,将加减号同时考虑,乘除号同时考虑。
读到加减号处理时运用算法如下:case '+':case '-':while(!EmptyStack(ps)) { /*当栈不为空时*/c2 = top(ps); /*将栈顶元素赋值给c2*/if(c2 =='+'|| c2 =='-'|| c2 == '*' || c2 == '/') {pop(ps); /*遇到加减号时栈中栈顶元素是加减乘除四种运算符出栈*/suffix[j++] = c2; /*将c2放入后缀表达式中*/}else if(c2=='(')break; /*遇到加减号时栈顶元素是左括号不进行出栈*/}push(ps, c1); /*c1入栈*/break;读到乘除号处理时算法与加减法基本一致,但在if语句时只需考虑c2 == '*' || c2 == '/'。
计算后缀表达式时读到数值时计算sum的值switch(c) {case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':if(set == 1) /*遇到操作数*/sum = sum * 10 + c - '0'; /*sum的计算*/else /*所遇到的不是操作数*/sum = c - '0';/*sum的计算*/set=1;break;考虑遇到空格、制符表和运算符时sum值的入栈情况case ' ':case'\t':case '\n':if (set == 1) {push(ps, sum); /*遇到空格或制表符sum入栈*/set = 0; }break;case '+':case '-':case '*':case '/':if(set == 1) {push(ps, sum); /*遇到运算符时sum入栈*/set = 0; }遇到加减乘除四个运算符时将栈顶和次栈顶元素分别运用所遇到运算符进行运算,并将运算结果入栈num2 = top(ps); /*栈顶元素赋值给num2*/pop(ps); /*元素出栈*/if(EmptyStack(ps)) { /*当栈为空*/free(ps); /*释放栈内空间*/return 0;}num1 = top(ps); /*栈顶元素赋值给num1*/pop(ps); /*元素出栈*/if(c == '+') { /*c为加号时*/push(ps, num1 + num2); /*num1与num2的和入栈*/}if(c == '-') { /*c为减号时*/push(ps, num1 - num2); /*num1与num2的差入栈*/}if(c == '*'){ /*c为乘号时*/push(ps, num1 * num2); /*num1与num2的积入栈*/}if(c == '/'){ /*c为除号时*/push(ps, num1 / num2); /*num1与num2的商入栈*/}break;default:free(ps);return 0; }}}该部分为程序的核心算法,即将算术表达式的值正确的输出。
4)主函数基本的数据定义,并实现表达式的输入,并调用getline()函数void main() {char c, infix[MAXNUM], suffix[MAXNUM];int result;int flag = 1;while(flag == 1) {printf("请输入任意一个整数算术表达式:\n");getline(infix, MAXNUM); /*调用getline()函数*/if(its(infix, suffix) == 1) {printf("所得后缀为:%s\n", suffix);}else {printf("无效缀!\n");}调用calculateSuffix()函数使程序完整if(calculateSuffix(suffix, &result) == 1){ /*调用calculateSuffix()函数*/ printf("结果为:%d\n", result);}else {printf("非法后缀!\n");}四、上机调试1.编程中遇到的几个问题刚看到题目的时候,我对题意没有理解,运用的普通的方法来完成程序,运行时输入无括号的算术表达式可以正确输出结果,但输入带括号的表达式时输出的结果与运算结果不符。