数据结构课程设计算术表达式求值的实现.docx
《数据结构课程设计算术表达式求值的实现.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计算术表达式求值的实现.docx(15页珍藏版)》请在冰豆网上搜索。
数据结构课程设计算术表达式求值的实现
课程设计报告
课程设计名称:
数据结构课程设计
课程设计题目:
算术表达式求值的实现
院(系):
*****
专业:
*****
班级:
*****
学号:
*****
姓名:
*****
指导教师:
*****
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.2.2流程图分析
1.Precede(charc1,charc2)判断运算符优先权,返回优先权高的。
算符间的优先关系如下:
表2.1运算符优先关系列表
+
-
*
/
(
)
#
+
>
<
<
<
<
>
>
-
>
>
<
<
<
>
>
*
>
>
>
>
<
>
>
/
>
>
>
>
<
>
>
(
<
<
<
<
<
=
)
>
>
>
>
>
>
#
<
<
<
<
<
=
2.intEvalExpr()主要操作函数。
算法概要流程图:
图2.2主要操作函数流程图
3.入栈出栈主要流程。
图2.3入栈出栈主要流程图
3数据结构分析
3.1存储结构
因为表达式是由操作符,运算符和界限符组成的。
如果只用一个char类型栈,不能满足2位以上的整数,所以还需要定义一个int类型的栈用来寄存操作数。
/*定义字符类型栈*/
typedefstruct{
intstacksize;
char*base;
char*top;
}Stack;
/*定义整型栈*/
typedefstruct{
intstacksize;
int*base;
int*top;
}Stack2;
3.2算法描述
1.栈的基本功能。
InitStack(Stack*s)和InitStack2(Stack2*s)分别构造运算符栈与构造操作数栈,Push(Stack*s,charch)运算符栈插入ch为新的栈顶元素,Push2(Stack2*s,intch)操作数栈插入ch为新的栈顶元素,Pop(Stack*s)删除运算符栈s的栈顶元素,用p返回其值,Pop2(Stack2*s)删除操作数栈s的栈顶元素,用p返回其值,GetTop(Stacks)用p返回运算符栈s的栈顶元素,GetTop2(Stack2s)用p返回操作数栈s的栈顶元素。
2.其它功能分析。
(1)In(charch)判断字符是否是运算符功能,如果该字符是运算符返回1,实现该功能的算法return(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')'||ch=='#')。
(2)Precede(charc1,charc2)判断运算符优先权功能,该函数判断运算符c1,c2的优先权,具体优先关系参照表1。
(3)Operate(inta,charop,intb)操作数用对应的运算符进行运算功能。
运算结果直接返回。
(4)num(intn)求操作数的长度功能,需要用itoa函数把int型转换成字符串型,strlen函数可求字符长度。
(5)EvalExpr()主要操作函数运算功能。
4调试与分析
4.1调试过程
在调试程序是主要遇到一下几类问题:
1.在括号,分号,引号,或者数据类型上总发生错误。
2.在写EvalExpr()函数时,忘了指针的地址符值不用加*号。
3.运行程序时由于忘记更改中英文输入法,导致输入中文(),程序无法正cha常执行。
4.程序开始编写时我仅仅编写了整型数的计算,通过修改后改成浮点类型的运算,使程序可操作性更强。
4.2程序执行过程
1.请输入正确的表达式以‘#’结尾:
4*(7-2)#
表达式结果为:
20.000000
Pressanykeytocontinue
2.请输入正确的表达式以‘#’结尾:
11+123*4#
表达式结果为:
503.000000
Pressanykeytocontinue
3.请输入正确的表达式以‘#’结尾:
4.2*(5+1.2)#
表达式结果为:
26.040000
Pressanykeytocontinue
4.请输入正确的表达式以‘#’结尾:
42.6/(3.2+2.8)#
表达式结果为:
7.100000
Pressanykeytocontinue
参考文献
[1]严蔚敏,吴伟民.数据结构[M].北京:
清华大学出版社,2007.
[2]张长海,陈娟.C程序设计[M].北京:
高等教育出版社,2004.
[3]谭浩强.C程序设计[M].北京:
清华大学出版社,2005.
[4]丁峻岭.C语言程序设计[M].北京:
中国铁道出版社,2006.
[5]徐孝凯.数据结构实用教程[M].清华大学出版社,2006.
附录(关键部分程序清单)
程序代码
#include
#include
#include
#defineNULL0
#defineOK1
#defineERROR-1
#defineSTACK_INIT_SIZE100
#defineSTACKINCREMENT20
/*定义字符类型栈*/
typedefstruct{
intstacksize;
char*base;
char*top;
}Stack;
/*定义整型栈*/
typedefstruct{
intstacksize;
float*base;
float*top;
}Stack2;
/*-----------------全局变量---------------*/
StackOPTR;/*定义运算符栈*/
Stack2OPND;/*定义操作数栈*/
charexpr[255]="";/*存放表达式串*/
char*ptr=expr;
intInitStack(Stack*s)//构造运算符栈
{
s->base=(char*)malloc(STACK_INIT_SIZE*sizeof(char));
if(!
s->base)returnERROR;
s->top=s->base;
s->stacksize=STACK_INIT_SIZE;
returnOK;
}
intInitStack2(Stack2*s)//构造操作数栈
{
s->base=(float*)malloc(STACK_INIT_SIZE*sizeof(float));
if(!
s->base)returnERROR;
s->stacksize=STACK_INIT_SIZE;
s->top=s->base;
returnOK;
}
intIn(charch)//判断字符是否是运算符,运算符即返回1
{
return(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')'||ch=='#');
}
intPush(Stack*s,charch)//运算符栈插入ch为新的栈顶元素
{
*s->top=ch;
s->top++;
return0;
}
intPush2(Stack2*s,floatch)//操作数栈插入ch为新的栈顶元素
{
*s->top=ch;
s->top++;
return0;
}
charPop(Stack*s)//删除运算符栈s的栈顶元素,用p返回其值
{
charp;
s->top--;
p=*s->top;
returnp;
}
floatPop2(Stack2*s)//删除操作数栈s的栈顶元素,用p返回其值
{
floatp;
s->top--;
p=*s->top;
returnp;
}
charGetTop(Stacks)//用p返回运算符栈s的栈顶元素
{
charp=*(s.top-1);
returnp;
}
floatGetTop2(Stack2s)//用p返回操作数栈s的栈顶元素
{
floatp=*(s.top-1);
returnp;
}
/*判断运算符优先权,返回优先权高的*/
charPrecede(charc1,charc2)
{
inti=0,j=0;
staticchararray[49]={
'>','>','<','<','<','>','>',
'>','>','<','<','<','>','>',
'>','>','>','>','<','>','>',
'>','>','>','>','<','>','>',
'<','<','<','<','<','=','!
',
'>','>','>','>','!
','>','>',
'<','<','<','<','<','!
','='};
switch(c1)
{
/*i为下面array的横标*/
case'+':
i=0;break;
case'-':
i=1;break;
case'*':
i=2;break;
case'/':
i=3;break;
case'(':
i=4;break;
case')':
i=5;break;
case'#':
i=6;break;
}
switch(c2)
{
/*j为下面array的纵标*/
case'+':
j=0;break;
case'-':
j=1;break;
case'*':
j=2;break;
case'/':
j=3;break;
case'(':
j=4;break;
case')':
j=5;break;
case'#':
j=6;break;
}
return(array[7*i+j]);/*返回运算符*/
}
/*操作函数*/
floatOperate(floata,charop,floatb)
{
switch(op)
{
case'+':
return(a+b);
case'-':
return(a-b);
case'*':
return(a*b);
case'/':
return(a/b);
}
return0;
}
intnum(floatn)//返回操作数的长度
{
charp[10];
intpl;
itoa((int)n,p,10);//把整型转换成字符串型
pl=2*strlen(p);
returnpl;
}
floatEvalExpr()//主要操作函数
{
charc,theta,x;intn;
floatm;
floata,b;
c=*ptr++;
while(c!
='#'||GetTop(OPTR)!
='#')
{
if(!
In(c))
{if(!
In(*(ptr-1)))ptr=ptr-1;
m=atoi(ptr);//取字符串前面的数字段
n=num(m);
Push2(&OPND,m);
ptr=ptr+n;
c=*ptr++;
}
else
switch(Precede(GetTop(OPTR),c))
{
case'<':
Push(&OPTR,c);
c=*ptr++;
break;
case'=':
x=Pop(&OPTR);
c=*ptr++;
break;
case'>':
theta=Pop(&OPTR);
b=Pop2(&OPND);a=Pop2(&OPND);
Push2(&OPND,Operate(a,theta,b));
break;
}
}
returnGetTop2(OPND);
}
intmain()
{
printf("请输入正确的表达式以'#'结尾:
");
do{
gets(expr);
}while(!
*expr);
InitStack(&OPTR);/*初始化运算符栈*/
Push(&OPTR,'#');/*将#压入运算符栈*/
InitStack2(&OPND);/*初始化操作数栈*/
printf("表达式结果为:
%f\n",EvalExpr());
getchar();
return0;
}
课程设计总结:
这次课程设计让我更加了解大一学到的C和这个学期学到的数据结构。
课设题目要求不仅要求对课本知识有较深刻的了解,同时要求程序设计者有较强的思维和动手能力和更加了解编程思想和编程技巧。
这次课程设计让我有一个深刻的体会,那就是细节决定成败,编程最需要的是严谨,如何的严谨都不过分,往往检查了半天发现错误发生在某个括号,分号,引号,或者数据类型上。
就像我在写EvalExpr()函数时,忘了指针的地址符值不用加*号,这一点小小的错误也耽误了我几十分钟,所以说细节很重要。
程序设计时,也不要怕遇到错误,在实际操作过程中犯的一些错误还会有意外的收获,感觉课程设计很有意思。
在具体操作中这学期所学的数据结构的理论知识得到巩固,达到课程设计的基本目的,也发现自己的不足之出,在以后的上机中应更加注意,同时体会到C语言具有的语句简洁,使用灵活,执行效率高等特点。
发现上机的重要作用,特别算术表达式有了深刻的理解。
指导教师评语:
指导教师(签字):
年月日
课程设计成绩