表达式求值算法实现.docx
- 文档编号:24462650
- 上传时间:2023-05-27
- 格式:DOCX
- 页数:22
- 大小:119.50KB
表达式求值算法实现.docx
《表达式求值算法实现.docx》由会员分享,可在线阅读,更多相关《表达式求值算法实现.docx(22页珍藏版)》请在冰豆网上搜索。
表达式求值算法实现
湖南人文科技学院计算机科学技术系
课程设计说明书
课程名称:
数据结构
课程代码:
408024
题目:
表达式求值
年级/专业/班:
08级计算机科学与技术二班
学生姓名:
黄胜李业芝黄自强
黄沅涛姚洋
学号:
084082100840821108408212
0840821308408215
指导教师:
袁辉勇
开题时间:
2009年12月21日
完成时间:
2010年1月1日
目录
摘要1
一、引言2
二、设计目的与任务2
1、课程设计目的2
2、课程设计的任务3
三、设计方案3
1、需求分析3
2、概要设计3
3、详细设计5
4、程序清单9
四、调试分析与体会11
五、运行结果11
六、结论13
七、致谢14
八、参考文献14
摘要
在高级语言环境中算术表达上的结果是通过语言环境预设的算法的思想计算出来的,然而高级语言初学者并不了解表达式的计算过程和方法。
本文采用算符优先分析和堆栈的方法给出了算术表达式的计算过程。
所以本次课程设计的程序是在Windows系统上为用户解决包括加、减、乘、除以及括号在内的四则混合运算。
用户可通过键盘输入四则运算,经过程序运行之后,可以判断出用户所输入的表达式是否正确。
如果正确,就给出表达式的值;如果不正确,就提示输入有误。
关键词:
四则混合运算;高级语言;栈
Abstract
Thearithmeticexpressionresultisthealgorithmthoughtwhichsupposesinadvancethroughthelanguageenvironmentcalculatesinthehigherorderlanguageenvironment,howeverthehigherorderlanguagebeginnerdoesnotunderstandtheexpressionthecomputationprocessandthemethod.Thisarticleusedtheoperatorfirsttoanalyzeandthestorehousemethodhasgiventhearithmeticexpressioncomputa-tionprocess.Therefore,theprocedureinthiscurriculumdesignisthesolutionforusersonWindowssystems,includingadd,subtract,multiply,divideandbrackets,includingfourhybridoperation.Userscanenterviathekeyboard4operation,afteraprogramisrunning,youcandeterminetheuserenteredexpressioniscorrect.Ifcorrect,itgivesthevalueoftheexpression;ifnotcorrect,itpromptedanerror.
Keywords:
Fourmixedoperating;High-levelprogramminglanguage;Stack
《数据结构》课程设计
——表达式求值
一、引言
随着我国进一步的开放,我们需要扩大国际交流,加强学习国外的先进经验。
掌握国际的领先技术是我们的首要任务。
计算机技术发展异常迅速,内容更新很快,我们对计算机的了解程度也直接影响了我国的现代化和信息化的程度。
《数据结构》是计算机程序设计的重要理论技术基础,它不仅是计算机学科的核心课程,而且是其他理工专业的热门选修课。
数据结构研究的是世界上所有非数值量的信息结构及其处理方法,它不仅是计算机科学与技术相关专业十分重要的核心课程,也是应用数学、管理科学、环境规划等很多专业的一门重要基础课。
所有的计算机系统软件和应用软件都要用到各种类型的数据结构。
因此,对于所有想更好地运用计算机来解决实际问题得人们而言,仅掌握几种计算机程序设计语言是难以应付众多复杂的课题的。
要想有效地使用计算机、充分发挥计算机的性能,还必须学习和掌握好数据结构的有关知识。
打好《数据结构》这门课程的扎实基础,对于学习计算机专业的其他课程,如操作系统、编译原理、数据库管理系统、软件工程、人工智能等都是十分有益的。
本次课程设计的课题是表达式求值。
在表达式中我们必须考虑的运算符的优先性,而能够实现这一功能的就是栈了。
栈是一种重要的数据结构,是只能在某一端插入和删除的特殊线性表。
它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据。
本次课程设计的实例虽然比较简单,程序设计也不是很复杂,但是在课程设计之前我们还是做了很多准备的。
例如,在网上和一些资料上查找栈的应用。
由此我们觉得本次程序的设计过程也是一个学习过程,更是对复杂程序的一个学习过程,还能培养我们的数抽象能力。
因此,我们觉得这次课程设计是非常有意义的,能为我们今后学习面向过程的程序设计作一些铺垫。
二、设计目的与任务
1、课程设计目的
本次课程设计教学所要求达到的目的:
通过栈来实现表达式求值,并通过此次课程设计的训练,使学生巩固和加深对栈的理解,利用所学到的计算科学的理论知识,提高解决实际问题的能力,增强运算、编程和使用技术资料的技能,通过实际问题的分析设计、编程和调试,掌握应用软件的分析方法和工程设计方法,能正确阐述设计和实验结果。
2、课程设计的任务
问题描述:
输入一个带加、减、乘、除以及含有括号的数学表达式以#结尾。
输出此表达式的值。
通过这次课程设计,达到更加灵活的运用所学的理论和知识和方法,以及独立分析和解决问题的能力;培养实事求是、认真、严谨的科学态度和刻苦钻研不断创新的精神,逐步建立正确的全局观念。
三、设计方案
1、需求分析
1)本程序实现表达式的求值。
用户在约定的条件下,正确输入表达式,经过程序的运行之后,给出表达式的值。
2)本程序不仅能够实现正整数表达式的求值,还可以实现负数以及小数表达式的值。
且数据的上限没有限制。
3)但是本程序中,由于某些程序段要判断操作符的优先性,在这些程序段之中,由于用了“=”来表示操作符的优先是相同的。
因此在表达式中,我们用“#”代替“=”。
也就是说:
用户在输入表达式之后,必须要用“#”结束。
2、概要设计
1)堆栈数据类型(ADT)如下:
ADTstack
{数据对象:
D={ai|ai∈Elemset,i=1,2,…,n,n≧0}
数据关系:
R1={
约定an端为栈顶,ai端为栈底。
基本操作:
(1)InitStack(&S)
函数功能:
构造一个空栈S。
(2)GetTop(S,&e)
函数功能:
取栈顶元素。
(3)Push(&S,e)
函数功能:
元素入栈。
(4)Pop(&S,Se)
函数功能;元素出栈。
}ADTStack
2)存储结构
typedefstruct
{
inttop;
doublearray[N];
}NumStack;//存放实数的栈
typedefstruct
{
inttop;
chararray[N];
}OpStack;//存放操作符的栈
3)流程图
3、详细设计
在本次课程设计中,我们用到了栈这个重要的数据结构。
在实现程序的功能的时候,有很多重要的程序段是涉及栈方面的:
有栈的结构建立,入栈,出栈。
另外还有就是对表达式进行运算,判断运算符的优先级,对表达式的主体进行处理。
重要的程序段如下。
1)栈的结构
typedefstruct
{
inttop;
doublearray[N];
}NumStack;
typedefstruct
{
inttop;
chararray[N];
}OpStack;
本课程设计是通过栈为载体来实现程序的功能的,因此栈结构的建立是必不可少的。
以上两个程序段就是建立栈。
第一个是用来存放数字的栈,第二个是用来存放操作符的栈。
2)把字符转化为相应的整数
intCint(charmychar)
{
return(mychar-48);
}
上面的函数就是把字符转化为相应的整数。
由于在ASCLL编码中,字符与其相对应的数字之差48,所以函数值就要return(mychar-48)。
3)数字进栈和操作符进栈
voidPushNum(NumStack*numstack,doublenum)
{
numstack->top++;
numstack->array[numstack->top-1]=num;
}
voidPushOp(OpStack*opstack,charop)
{
opstack->top++;
opstack->array[opstack->top-1]=op;
}
数字和操作符在输入先放在栈里面。
而在入栈的时候,栈顶元素的指针先增加以增加存储的空间用来存放数字和操作符,之后才把数字和操作符存放到栈中。
第一个函数是数字的入栈,第二个函数是操作符的入栈。
4)数字出栈和操作符出栈
voidPopNum(NumStack*numstack,double*num)
{
*num=numstack->array[numstack->top-1];
numstack->top--;
}
voidPopOp(OpStack*opstack,char*op)
{
*op=opstack->array[opstack->top-1];
opstack->top--;
}
数字和操作符存放在栈中,由于运算的需要,此时就必须把数字和操作符从栈中取出来,即出栈。
数字和操作符的出栈,是先取出栈顶元素an。
由于取出元素之后,原先的栈顶元素的位置为空了。
此时an-1就成了栈顶元素了,所以原先的栈顶指针就减一,指向现在的栈顶元素an-1。
第一个函数是数字的出栈,第二个函数是操作符的出栈。
5)进行运算的函数
doubleCalc(doublea,doubleb,charc)
{
doubleresult;
switch(c){
case'+':
result=a+b;
break;
case'-':
result=a-b;
break;
case'*':
result=a*b;
break;
case'/':
result=a/b;
break;
}
returnresult;
}
当程序在遇到运算符的时候,就要进行运算。
在上面的函数中a和b就是代表数字,而c就是代表运算符。
当出栈时栈顶元素是“+”(加),程序就执行加法运算,最后的结果是a和b两数之和;当出栈时栈顶元素是“-”(减),程序就执行减法运算,最后的结果是a和b两数之差;当出栈时栈顶元素是“*”(乘),程序就执行乘法运算,最后的结果是a和b两数之积;当出栈时栈顶元素是“/”(除),程序就执行除法运算,最后的结果是a和b两数之商。
函数的返回值就是函数最后的结果。
6)判断优先级的函数
charPriority(chary,charx)
{
charpriority='<';
switch(x)
{
case'+':
case'-':
if(y=='('||y=='#')priority='>';
break;
case'*':
case'/':
if(y=='('||y=='#'||y=='+'||y=='-')priority='>';
break;
case'(':
priority='>';
break;
case')':
if(y=='(')priority='=';
break;
case'#':
if(y=='#')priority='=';
break;
default:
priority='E';
}
returnpriority;
}
由于我们输入的是四则运算,因此就不得不考虑操作符的优先级问题。
上述函数就是判断优先级的函数。
函数中x和y都代表操作符。
函数默认x优先级大于y。
但是当x为“+”或“-”时,且y为“(”或“#”的时,y优先级高于x;当x为“*”或“/”时,且y为“(”“#”“+”或“-”时,由于入栈和出栈的模式匹配的问题,此时y优先级也高于x;而当x为“(”时,x的优先级最高;当x为“)”且y为“(”时,x,y的优先级相同;当x为“#”且y为“#”时,x和y的优先级也相同。
经过运算之后,函数返回值即为优先级最高的操作符。
7)处理表达式主体的函数
voidProcess(NumStack*numstack,OpStack*opstack,charx)
{
doublea,b;charc;
staticdoubletempnum=0.00000000;
staticintlen=10;
staticintdot=0,flags=0;
if(isdigit(x)||x=='.')
{
if(x=='.')dot=1;
else
{
if(dot==0)
tempnum=tempnum*10+Cint(x);
else
{
tempnum=tempnum+(double)Cint(x)/len;
len*=10;
}
}
}
else{
if(flags==0&&x!
='(')
{
PushNum(numstack,tempnum);tempnum=0.00000000;len=10;dot=0;
}
switch(Priority(opstack->array[opstack->top-1],x))
{
case'>':
PushOp(opstack,x);flags=0;
break;
case'<':
PopOp(opstack,&c);
PopNum(numstack,&b);
PopNum(numstack,&a);
PushNum(numstack,Calc(a,b,c));
flags=1;
Process(numstack,opstack,x);
break;
case'=':
PopOp(opstack,&c);flags=1;
break;
default:
printf("WrongExpress!
");
exit(0);
}
}
}
在进行完把字符转化为相应的数字,以及判断操作符的优先级之后。
我们就必须要对表达式进行处理。
上述的函数就是处理表达式的函数。
函数首先判断,如果x是“.”(小数点)。
则将小数点之后的数值,也就是小数部分先进行计算。
计算完小数部分之后,再对整数部分进行计算。
最后整数部分和小数部分相加。
在判断操作符优先级的时候。
如果输入的字符不是“(”,则入栈。
当在判断操作符的栈顶元素和即将入栈元素优先级的时候。
如果栈顶元素的优先级高于即将入栈元素的时候,则这个即将入栈的元素就入栈。
如果小于的话,则操作符栈顶元素出栈,且数字栈的栈顶元素出栈,然后函数调用自己,直到运算完整个表达式为止。
如果优先级相同,则全部出栈。
并将计算后的值存放到另外一个栈中。
这样整个表达式的值就求出来了。
4、程序清单
#defineN50
#include
#include
#include
#include
typedefstruct
{inttop;doublearray[N];}NumStack;
typedefstruct
{inttop;chararray[N];}OpStack;
intCint(charmychar)
{return(mychar-48);}
voidPushNum(NumStack*numstack,doublenum)
{numstack->top++;numstack->array[numstack->top-1]=num;}
voidPopNum(NumStack*numstack,double*num)
{*num=numstack->array[numstack->top-1];numstack->top--;}
voidPushOp(OpStack*opstack,charop)
{opstack->top++;opstack->array[opstack->top-1]=op;}
voidPopOp(OpStack*opstack,char*op)
{*op=opstack->array[opstack->top-1];opstack->top--;}
doubleCalc(doublea,doubleb,charc)
{doubleresult;
switch(c)
{case'+':
result=a+b;break;
case'-':
result=a-b;break;
case'*':
result=a*b;break;
case'/':
result=a/b;break;
}
returnresult;
}
charPriority(chary,charx)
{charpriority='<';
switch(x)
{case'+':
case'-':
if(y=='('||y=='#')priority='>';break;
case'*':
case'/':
if(y=='('||y=='#'||y=='+'||y=='-')priority='>';break;
case'(':
priority='>';break;
case')':
if(y=='(')priority='=';break;
case'#':
if(y=='#')priority='=';break;
default:
priority='E';
}
returnpriority;
}
voidProcess(NumStack*numstack,OpStack*opstack,charx)
{doublea,b;charc;
staticdoubletempnum=0.00000000;
staticintlen=10;
staticintdot=0,flags=0;
if(isdigit(x)||x=='.')
{if(x=='.')dot=1;
else
{if(dot==0)tempnum=tempnum*10+Cint(x);
else
{tempnum=tempnum+(double)Cint(x)/len;len*=10;}
}
}
else{if(flags==0&&x!
='(')
{PushNum(numstack,tempnum);
tempnum=0.00000000;len=10;dot=0;
}
switch(Priority(opstack->array[opstack->top-1],x))
{case'>':
PushOp(opstack,x);flags=0;break;
case'<':
PopOp(opstack,&c);PopNum(numstack,&b);
PopNum(numstack,&a);PushNum(numstack,Calc(a,b,c));flags=1;
Process(numstack,opstack,x);break;
case'=':
PopOp(opstack,&c);flags=1;break;
default:
printf("WrongExpress!
");exit(0);
}
}
}
voidmain()
{NumStacknumstack;OpStackopstack;
chars[N];
inti=0;inta,b,c;numstack.top=0;opstack.top=0;
PushOp(&opstack,'#');
printf("表达式求值问题");
printf("\n\t\t\t1.请输入表达式并以#结束:
\n");
printf("\t\t\t2.输出表达式的结果:
\n");
printf("\t\t\t3.退出\n");printf("\n");
while(c!
=3)
{printf("\t\t\t*请选择功能--");scanf("%d",&a);
printf("\t\t\t输入表达式并以#结束:
\n");printf("\t\t\t");
if(a==1)scanf("%s",&s);
for(i=0;i printf("\t\t\t*请选择功能--");scanf("%d",&b); if(b==2) printf("\t\t\t表达式结果: \n\t\t\t%.2f\n",numstack.array[numstack.top-1]); printf("\t\t\t*请选择功能--");scanf("%d",&c); }printf("\t\t\t结束! \n"); } 四、调试分析与体会 本次课程设计的实例虽然比较简单,程序设计也不是很复杂。 但是在程序的编写和调试过程中,我们还是遇到了一些问题。 这些问题有些完全是自己的粗心造成的,有的却是一些由于我们自身的知识面不广造成的。 这些问题提示我
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 表达式 求值 算法 实现