算术表达式求值课设报告.docx
《算术表达式求值课设报告.docx》由会员分享,可在线阅读,更多相关《算术表达式求值课设报告.docx(16页珍藏版)》请在冰豆网上搜索。
![算术表达式求值课设报告.docx](https://file1.bdocx.com/fileroot1/2022-12/12/4a1b804c-b4f1-4349-a44c-dd4831d57811/4a1b804c-b4f1-4349-a44c-dd4831d578111.gif)
算术表达式求值课设报告
数据结构课程设计
设计说明书
表达式求值算法的实现
〔〔〔〕〔〕〔〔
学生
学号
班级
成绩
指导教师
数学与电脑科学学院
2012年9月7日
数据结构课程设计评阅书
题目
表达式求值算法的实现
学生
学号
指导教师评语及成绩
成绩:
教师签名:
年月日
答辩教师评语及成绩
成绩:
教师签名:
年月日
教研室意见
总成绩:
室主任签名:
年月日
注:
指导教师成绩60%,答辩成绩40%,总成绩合成后按五级制记入
课程设计任务书
2011—2012学年第2学期
专业学号:
:
课程设计名称:
数据结构课程设计
设计题目:
表达式求值算法的实现
完成期限:
自2012年8月28日至2012年9月7日共2周
栈的存储和相关运算是数据结构中数组部分的重点知识和技能。
表达式求值算法可借助栈来完成,它的存储可以使用顺序结构也可以使用链式结构,这要根据具体的应用来决定。
本课程设计按以下的要求运用C/C++结构体、指针、数据结构等基知识编程实现。
任务要求:
1〕阐述设计思想,画出流程图;2〕任意输入一个表达式〔算术、逻辑、关系表达式〕;3〕建立栈;4〕借助栈的相关运算完成表达式求值过程;5〕将表达式及其运算结果按照其数学形式打印输出;6〕说明测试方法,写出完整的运行结果,较好的界面设计;7〕按照格式要求完成课程设计说明书。
设计要求:
1〕问题分析和任务定义:
根据设计题目的要求,充分地分析和理解问题,明确问题要求做什么?
〔而不是怎么做?
〕限制条件是什么?
确定问题的输入数据集合。
2〕逻辑设计:
对问题描述中涉及的操作对象定义相应的数据类型,并按照以数据结构为中心的原则划分模块,定义主程序模块和各抽象数据类型。
逻辑设计的结果应写出每个抽象数据类型的定义〔包括数据结构的描述和每个基本操作的功能说明〕,各个主要模块的算法,并画出模块之间的调用关系图;
3〕详细设计:
定义相应的存储结构并写出各函数的伪码算法。
在这个过程中,要综合考虑系统功能,使得系统结构清晰、合理、简单和易于调试,抽象数据类型的实现尽可能做到数据封装,基本操作的规格说明尽可能明确具体。
详细设计的结果是对数据结构和基本操作做出进一步的求精,写出数据存储结构的类型定义,写出函数形式的算法框架;
4〕程序编码:
把详细设计的结果进一步求精为程序设计语言程序。
同时加入一些注解和断言,使程序中逻辑概念清楚;
5〕程序调试与测试:
能够熟练掌握调试工具的各种功能,设计测试数据确保程序正确。
调试正确后,认真整理源程序及其注释,形成格式和风格良好的源程序清单和结果;
6〕结果分析:
程序运行结果包括正确的输入及其输出结果和含有错误的输入及其输出结果。
算法的时间、空间复杂性分析;
7〕编写课程设计报告;
指导教师〔签字〕:
教研室主任〔签字〕:
批准日期:
年月日
摘要
本次课程设计利用编程软件,运用c语言、指针、结构体、数据结构中栈的相关知识编写了表达式求值算法的程序。
为了实现算符优先算法使用两个工作栈,一个称为OPTR,用以寄存运算符;另一个称做OPND,用以寄存操作数或运算结果。
依次读入表达式,假设是操作符即进OPND栈,假设是运算符则和OPTR栈的栈顶运算符比较优先权后作相应的操作,直至整个表达式求值完毕,最终实现了任意表达式求值的简单运算。
关键词:
指针;结构体;栈
1课题描述
随着现代科学技术的迅猛发展,电脑技术已经渗透到各个领域,成为各行业必不可少的工具.借助现从识经济时代的特点,对国民经济建设提出了“用信息化带开工业化”的指导思想。
对常用算法的实现与比较操作校管而言,全面开发和应用电脑操作系统就是近期不能回避的问题。
由于电脑技术的发展,许多复杂的数值问题才得以解决。
一个数学问题,乃至一个数值计算公式,如何在电脑上实现,而在电脑处理计算的过程中又会产生哪些新问题,这是在实际应用算法操作中经常会遇到的课题。
在电脑中,算术表达式由常量、变量、运算符和括号组成。
由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行。
因而在程序设计时,借助栈实现。
算法输入:
一个算术表达式,由常量、变量、运算符和括号组成〔以字符串形式输入〕。
为简化,规定操作数只能为正整数,操作符为+、-*、/,用#表示结束。
算法输出:
表达式运算结果。
算法要点:
设置运算符栈和运算数栈辅助分析算符优先关系。
在读入表达式的字符序列的同时,完成运算符和运算数的识别处理,以及相应运算。
开发工具:
VisualC++
2设计要求
运用c/c++、指针、结构体、数据结构中栈的相关知识编写任意表达式求值算法的实现。
主函数只要是表达式的输入再通过调用EvaluateExpression()函数进行运算数、运算符等相关处理,最后输出结果。
如图
总体规划图
3逻辑设计与分析
3.1举例分析
如下表是对3*(7-2)的求值分析步骤。
特别说明当在计算除法运算时如果分母为’0’,则出现错误提示。
步骤
OPTR栈
OPND栈
输入字符
主要操作
1
#
3*(7-2)#
Push(OPND,’3’)
2
#
3
*(7-2)#
Push(OPTR,’*’)
3
#*
3
(7-2)#
Push(OPNR,’(’)
4
#*(
3
7-2)#
Push(OPND,’7’)
5
#*(
37
-2)#
Push(OPNR,’-’)
6
#*(-
37
2)#
Push(OPND,’2’)
7
#*(-
372
)#
Operate(‘7’,’-’,’2’)
8
#*(
35
)#
Pop(OPTR)
9
#*
35
#
Operate(‘3’,’*’,5’)
10
#
15
#
Return(GetTop2(OPND))
表3.1例子分析
核心
为了实现算符优先算法。
可以使用两个工作栈。
一个称为OPTR,用以寄存运算符,另一个称做OPND,用以寄存操作数或运算结果。
〔1〕首先置操作数栈为空栈,表达式起始符”#”为运算符栈的栈底元素;
〔2〕依次读入表达式,假设是操作符即进OPND栈,假设是运算符则和OPTR栈的栈顶运算符比较优先权后作相应的操作,直至整个表达式求值完毕〔即OPTR栈的栈顶元素和当前读入的字符均为”#”〕。
4算法流程图
4.1主算法流程图
如下列图4.1给出了主要算法控制流程图:
/**************************************
算术表达式求值的算符优先算法。
设OPTR和OPND分别为运算符栈和运算数栈,OPSET为运算符集合。
***************************************/
SqStackOPTR;//运算符栈,字符元素
SqStackOPND;//运算数栈,实数元素
charTempData[20];
floatData,a,b;
chartheta,c,x,Dr[2];
InitStack,char>(OPTR);
Push(OPTR,'#');
InitStack,float>(OPND);
strcpy(TempData,"\0");//将TempData置为空
c=getchar();
while(c!
='#'||GetTop,char>(OPTR)!
='#')
{
if(!
In(c,OPSET))
{
Dr[0]=c;
Dr[1]='\0';//存放单个数
strcat(TempData,Dr);//将单个数连到TempData中,形成字符串
c=getchar();
if(In(c,OPSET))//如果遇到运算符,则将字符串TempData转换成实数,入栈,
并重新置空
{
Data=(float)atof(TempData);
Push(OPND,Data);
strcpy(TempData,"\0");
}
}
else
{//不是运算符则进栈
switch(precede(GetTop,char>(OPTR),c)){
case'<':
//栈顶元素优先权低
Push(OPTR,c);
c=getchar();
break;
case'=':
//脱括号并接收下一字符
Pop(OPTR,x);
c=getchar();
break;
case'>':
//退栈并将运算结果入栈
Pop(OPTR,theta);
Pop(OPND,b);
Pop(OPND,a);
Push(OPND,Operate(a,theta,b));
break;
}//switch
}
}//while
returnGetTop,float>(OPND)}
5详细设计
5.1顺序栈的建立
任何一个表达式都是由操作符,运算符和界限符组成的。
分别用顺序栈来寄存表达式的操作数和运算符。
栈是限定于紧仅在表尾进行插入或删除操作的线性表。
顺序栈的存储结构是利用一组连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置,base为栈底指针,在顺序栈中,它始终指向栈底,即top=base可作为栈空的标记,每当插入新的栈顶元素时,指针top增1,删除栈顶元素时,指针top减1。
typedefintStatus;
template
structSqStack
{
T*top;
T*base;
intstacksize;
};顺序栈结构
template
StatusInitStack(T1&S)
{
S.base=(T2*)malloc(STACK_INIT_SIZE*sizeof(T2));
if(!
S.base)exit(overflow);
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
returnok;
}初始化栈函数
template
StatusPush(T1&S,T2e)
{
if(S.top-S.base>=S.stacksize)
{
S.base=(T2*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(T2));
if(!
S.base)exit(overflow);
S.top=S.base+S.stacksize;
S.stacksize+=STACKINCREMENT;
}
*S.top++=e;
returnok;
}入栈函数
template
StatusPop(T1&S,T2&e)
{
if(S.top==S.base)returnerror;
e=*--S.top;
returnok;
}出栈函数
template
T2GetTop(T1S)
{
if(S.top==S.base)
returnerror;
else
return*(S.top-1);
}获取栈顶元素
5.2函数及对应程序
(1)In(charTest,char*TestOp)判断字符是否是运算符功能,运算符即返回ture。
StatusIn(charTest,char*TestOp){
boolFind=false;
for(inti=0;iif(Test==TestOp[i])Find=true;
}
returnFind;
}//判断是否为运算符
(2)ReturnOpOrd(charop,char*TestOp)判断运算符优先权功能,该函数判断运算符Aop,Bop的优先权。
判断运算符优先权,返回优先权高的。
intReturnOpOrd(charop,char*TestOp){
inti;
for(i=0;iif(op==TestOp[i])returni;
}
return0;
}
charprecede(charAop,charBop){
returnPrior[ReturnOpOrd(Aop,OPSET)][ReturnOpOrd(Bop,OPSET)];
}//ReturnOpOrd和precede组合,判断运算符优先级
算符间的优先关系如下:
+
-
*
/
(
)
#
+
>
<
<
<
<
>
>
-
>
>
<
<
<
>
>
*
>
>
>
>
<
>
>
/
>
>
>
>
<
>
>
(
<
<
<
<
<
=
)
>
>
>
>
>
>
#
<
<
<
<
<
=
(3)Operate(floata,unsignedchartheta,floatb)操作数用对应的运算符进行运算功能。
运算结果直接返回。
floatOperate(floata,unsignedchartheta,floatb){
switch(theta){
case'+':
returna+b;
case'-':
returna-b;
case'*':
returna*b;
case'/':
{if(b!
=0)returna/b;
elseprintf("输入错误请重输");}//判断分母是否为零为零则重新输入
default:
return0;
}
}//运算
(4)EvaluateExpression()主要操作函数,功能主要实现表达式的整体计算
floatEvaluateExpression(){
算术表达式求值的算符优先算法,设OPTR和OPND分别为运算符栈和运算数栈,OPSET为运算符集合。
SqStackOPTR;//运算符栈,字符元素
SqStackOPND;//运算数栈,实数元素
charTempData[20];
floatData,a,b;
chartheta,c,x,Dr[2];
InitStack,char>(OPTR);
Push(OPTR,'#');
InitStack,float>(OPND);
strcpy(TempData,"\0");//将TempData置为空
c=getchar();
while(c!
='#'||GetTop,char>(OPTR)!
='#')
{
if(!
In(c,OPSET))
{
Dr[0]=c;
Dr[1]='\0';//存放单个数
strcat(TempData,Dr);//将单个数连到TempData中,形成字符串
c=getchar();
if(In(c,OPSET))//如果遇到运算符,则将字符串TempData转换成实数,入栈,
//并重新置空
{
Data=(float)atof(TempData);
Push(OPND,Data);
strcpy(TempData,"\0");
}
}
else
{//不是运算符则进栈
switch(precede(GetTop,char>(OPTR),c)){
case'<':
//栈顶元素优先权低
Push(OPTR,c);
c=getchar();
break;
case'=':
//脱括号并接收下一字符
Pop(OPTR,x);
c=getchar();
break;
case'>':
//退栈并将运算结果入栈
Pop(OPTR,theta);
Pop(OPND,b);
Pop(OPND,a);
Push(OPND,Operate(a,theta,b));
break;
}}}returnGetTop,float>(OPND);
}
6程序测试
〔1〕程序运行成功后界面
图6.1运行成功界面
〔2〕任意输入表达式3*(2+4)
图6.2表达式输入界面
〔3〕按‘#’号键结束,结果输出
当分母输入‘0’时错误输入提示
总结
本次课设基本上实现了任意加、减、成、除的计算。
可以对分母输入错误时进行错误提示。
不足之处本次程序只是实现了加、减、成、除的简单运算还没有到达真正的实现各种表达式输入的计算,比方根号、指数等计算,所以可以通过进一步设计使其到达各种输入计算。
这次课程设计让我更加了解大一学到的C,课设题目要求不仅要求对课本知识有较深刻的了解,同时要求程序设计者有较强的思维和动手能力和更加了解编程思想和编程技巧。
这次课程设计让我有一个深刻的体会,那就是细节决定成败,编程最需要的是严谨,如何的严谨都不过分,往往检查了半天发现错误发生在某个括号,分号,引号,或者数据类型上,所以说细节很重要。
程序设计时,也不要怕遇到错误,在实际操作过程中犯的一些错误还会有意外的收获,感觉课程设计很有意思。
在具体操作中对所学的数据结构的理论知识得到稳固,到达课程设计的基本目的,也发现自己的不足之出,在以后的上机中应更加注意,同时体会到C语言具有的语句简洁,使用灵活,执行效率高等特点。
发现上机的重要作用,特别对算术表达式有了深刻的理解。
这个程序不光是我一个人就能能完成的,在课设的过程中总会遇到这样那样的问题,经过和同学的讨论老师的帮助最终才完成了这次课程设计,所以很感谢我的课设老师以及帮助我的同学。
查考文献
[2]田淑清,周海燕.C语言程序设计[M]