华东交大数据结构课设 表达式求值.docx
《华东交大数据结构课设 表达式求值.docx》由会员分享,可在线阅读,更多相关《华东交大数据结构课设 表达式求值.docx(27页珍藏版)》请在冰豆网上搜索。
![华东交大数据结构课设 表达式求值.docx](https://file1.bdocx.com/fileroot1/2022-12/30/065aba6a-165f-4820-a704-45b35834d644/065aba6a-165f-4820-a704-45b35834d6441.gif)
华东交大数据结构课设表达式求值
课程设计(论文)任务书
学 院 专 业 班
一、课程设计(论文)题目
二、课程设计(论文)工作自年月日起至年月日止。
三、课程设计(论文)地点:
四、课程设计(论文)内容要求:
1.课程设计的目的
为了配合《数据结构》课程的教学,使学生能更深刻的领会《数据结构》课程的
重要性,特开设此课程设计;编写一些在特定数据结构上的算法,通过上机调试,更
好的掌握各种数据结构及其特点,培养学生综合运用所学理论知识解决复杂实际问题
的实践能力、研究性学习能力和团队合作能力。
2.课程设计的任务及要求
1)基本要求
(1)课程设计前必须选定课程设计题目,并认真进行需求分析与系统设计;
(2)上机调试之前要认真准备实验程序及调试时所需的测试数据;
(3)独立思考,独立完成,严禁抄袭,调试过程要规范,认真记录调试结果;
(4)上机结束后认真规范撰写课设报告,对设计进行总结和讨论。
2)课程设计论文编写要求
(1)要按照书稿的规格撰写打印课设论文
(2)论文包括任务书、目录、绪论、正文、总结、参考文献、附录等
(3)正文中要有问题描述、抽象数据类型的定义、数据的存储结构、设计的求解
算法、算法的实现、调试分析与测试结果
(4)课设论文装订按学校的统一要求完成
3)课设考核
从以下几方面来考查:
(1)考勤和态度;
(2)任务的难易程度及设计思路;
(3)动手调试能力;
(4)论文撰写的水平、格式的规范性。
4)参考文献
[1]严蔚敏,吴伟民.数据结构(C语言版)[M].北京:
清华大学出版社,2007年.
[2]严蔚敏,吴伟民.数据结构题集(C语言版)[M].北京:
清华大学出版社,2007年.
[3]谭浩强.C语言程序设计[M].北京:
清华大学出版社,2006年.
5)课程设计进度安排
内容天数 地点
构思及收集资料1 图书馆
程序设计与调试3 计算机房
撰写论文1 图书馆
6)任务及具体要求
表达式求值,可供小学生作业,并能给出分数
任务要求:
1)建立试题库文件,随机产生n个题目;
2)随时可以退出;
3)题目涉及加减乘除,带括号的混合运算;
4)保留历史分数,能回顾历史,给出与历史分数比较后的评价。
学生签名:
__________
年月日
课程设计(论文)评审意见
(1)考勤和态度:
优( )、良( )、中( )、一般( )、差( )
(2)任务难易及设计思路 :
优( )、良( )、中( )、一般( )、差( )
(3)动手调试能力评价 :
优( )、良( )、中( )、一般( )、差( )
(4)论文撰写水平及规范性评价:
优( )、良( )、中( )、一般( )、差( )
评阅人:
职称:
讲师
年月日
目录
目录1
1.绪论1
1.1需求分析1
1.1.1市场需求1
1.1.2软件功能需求1
1.2实验意义2
2.程序框架设计2
2.1概要设计2
3.元素存储结构6
4.详细设计7
4.1程序算法7
4.2函数说明7
5功能测试9
5总结12
参考文献13
附录14
1.绪论
1.1需求分析
1.1.1市场需求
为了适应市场小学生的题目需求以及节约纸张,顾开发此程序以来到达即可以节约纸张又可以通过做题来提高小学生的运算能力。
而且,题目库可以自己定制,适合于各给不同能力段的小学生,达到普及以及减轻社会纸张压力。
同时,培养小学生养成良好使用电脑的习惯。
1.1.2软件功能需求
该题目的核心是利用栈这种数据结构来实现一个加减乘除以及带括弧的混合数学表达式的计算。
其次是利用文件来保存和读写试题库、每次做题的成绩和以往成绩的平均值。
对于数学表达式的计算,可以设置一个运算符栈和一个数字栈,分别来保存运算符、数字或者中间计算得到的结果。
将整个表达式看做一个字符串,从开头依次判断每个字符是运算符还是数字,若是运算符,则根据运算符优先级来确定是将其压栈还是弹栈进行计算;若是数字,则先将其转化并计入一个临时int型变量中,看下一个字符是否为运算符栈,若是,则将临时变量压进数字栈,否则读取下一个数字字符并进行相关处理后累加到临时变量中,直到下一个字符为运算符,将临时变量压进数字栈。
最后,当字符为"="时,结束计算,得到计算结果。
对于试题库,第一次运行程序时需要用户输入若干试题来建立试题库文件,再次运行时磁盘上已经存在试题库文件,故不需再次建立试题库,直接读取文件即可。
然后从试题库中通过随机数函数随机抽取若干个试题供用户来做测试。
测试过程中可即时跟踪判断用户所给答案是否正确,并给出相关提示。
测试完毕后给出本次测试得分,对得分进行评价并将得分存到磁盘文件上。
用户可随时查看成绩的历史记录以及其平均成绩,可随时选择退出程序。
1.2实验意义
通过对软件的编写来了解银行业务办理过程。
增加动手实践能力。
提高对程序的编写,调试和开发能力。
通过对论文的撰写来提高论文撰写能力。
明确系统的需求,明确软件开发的最终目的,使开发出来的软件更能符合客户的需求。
2.程序框架设计
本程序主要用到的结构为栈。
2.1概要设计
1)为了能够实现上述软件需求功能,先定义栈的抽象数据类型
ADTQueue={
数据对象:
D={ai|ai=ElemType,i=0,1,2···,n,n>=0}
数据关系:
R={|ai,ai+1=D}
基本操作:
InitStack(&S)
操作结果:
构造一个空栈S
DestroyStack(&S)
初始条件:
栈已经存在
操作结果:
栈S被销毁
ClearStack(&S)
初始条件:
栈已存在
操作结果:
将S清空为空栈
StackEmpty(S)
初始条件:
栈已存在
操作结果:
若栈为空,若返回1,否则返回0
Stacklength(S)
初始条件:
栈S存在
操作结果:
返回S元素的个数,栈的长度
Menu()
操作结果:
在屏幕上显示操作菜单.
}//ADTQueue
2)本程序包含19个函数
(1)主函数main()
(2)intNumInitStack(Num*S1)//构造数字栈
(3)intOperInitStack(Oper*S2)//构造运算符栈
(4)intNumGetTop(Num*S1)//得到数字栈栈顶元素
(5)charOperGetTop(Oper*S2)//得到运算符栈栈顶元素
(6)voidNumPush(Num*S1,inte1)//数字栈压栈
(7)voidOperPush(Oper*S2,chare2)//运算符栈压栈
(8)intNumPop(Num*S1)//数字栈弹栈
(9)charOperPop(Oper*S2)//运算符栈弹栈
(10)charPrecede(chara,charb)//判断运算符优先级
(11)intOperate(inta,chartheta,intb)//计算二元表达式的值
(12)intIsOper(charch)//判断字符ch是否为运算符
(13)intResult(chara[],Num*num,Oper*oper)//计算表达式的结果
(14)intBuildshitiku()//建立试题库
(15)voidXuanti(intn,inta[])//随机选取n个题目,将题号保存在数组a中
(16)voidAvescore()//求平均成绩
(17)voidZuoti(Shitia[])//做题
(18)voidHistory()//输出历史成绩
(19)intmenu()//菜单函数
3)各函数间关系如下图2.1-1所示:
2.2程序流程图
如图-2.2-
(1)为程序流程图,主要描述了该程序运行过程。
图2.2:
程序图
3.元素存储结构
如图所示为Num;数字栈类型
typedefstruct
{
int*base,*top;
intsize;
}Num;//数字栈
int*base,*top
intsize
图-3-1:
数字栈结构体
如图Shiti试题数据类型
typedefstruct
{
chara[100];
intresult;
}Shiti;//试题数据类型
chara[100];
intresul
图3-2:
Shiti试题数据类型
如图是运算符栈类型
typedefstruct
{
char*base,*top;
intsize;
}Oper;//运算符栈
char*base,*top;
intsize;
图3-3:
运算符栈类型
4.详细设计
4.1程序算法
本次的课程数据我是用栈来实现表达式求解,利用栈求表达式的值,可供小学生作业,并能给出分数。
要求:
建立试题库文件,随机产生n个题目;题目涉及加减乘除,带括弧的混合运算;随时可以退出;保留历史分数,能回顾历史,给出与历史分数比较后的评价。
我利用文件来保存和读写试题库,且要运用磁盘文件。
数学表达式的计算,我设置了一个运算符栈与一个数字栈,分别来保存运算符、数字或者中间计算得到的结果。
将表达式看成一个字符串,从而分种计算。
⑴通过输入的表达式来建立试题库。
⑵对从键盘输入的的表达式通过算符栈和数字栈进行压栈和出栈。
⑶.通过菜单按钮进行选择,做题,查看历史分数,退出。
4.2函数说明
4.2.1main()
在主函数中调用子函数进行初始化,调用函数执行程序模拟,控制程序的进行。
4.2.2intBuildshitiku()
建立试题库,通过txt文件进行保存。
4.2.3intNumInitStack(Num*S1)
构造数字栈,申请空间,初始化数字栈。
4.2.4intOperInitStack(Oper*S2)
构造算符栈,申请空间,初始化算符栈。
4.2.5intNumGetTop(Num*S1)
得到数字栈的栈顶元素,以来入栈。
4.2.6charOperGetTop(Oper*S2)
得到运算符栈顶元素,以便入栈。
4.2.7voidNumPush(Num*S1,inte1)
数字栈压栈,也就是所谓的入栈。
4.2.8voidOperPush(Oper*S2,chare2)
函运算符栈压栈,入栈。
4.2.9intNumPop(Num*S1)
数字栈出栈。
4.2.10charOperPop(Oper*S2)
运算符出栈,返回一个字符。
4.2.11charPrecede(chara,charb)
将判断运算符的优先级,以来计算表达式。
4.2.12intOperate(inta,chartheta,intb)
计算表达式的值,通过表达式运算规则从左到右,先乘除后加减,先括号内在括号外的顺序去计算。
4.2.13voidXuanti(intn,inta[])
在已建好的试题库中,通过随机抽取n个题目,保存在数组中。
4.2.14voidZuoti(Shitia[]
首做题,通过输入的题数,在试题库中随机抽取题目,输入答案,通过表达式求解出答案。
4.2.15voidHistory()
将以往的做题成绩保留在内存中,通过调用函数给出成绩。
4.2.16)intmenu()
菜单函数。
4.2.17intIsOper(charch)
判断字符ch是否为运算符
4.2.18voidAvescore()
求出平均成绩,在给出的分数以及题数给出平均成绩。
5功能测试
(1)首次运行程序时如图5-1。
图5-1:
程序初运行图
(2)依次输入所要建立的试题数目n和n个表达式,现以输入十个为例,实际可多输入一些,如图5-2.
图5-2:
建立试题库
(3)任意键,跳出菜单页面,如图5-3
图5-3:
菜单图
(4)选择1,进行做题。
如图5-4.
图5-4:
做题
(5)选择2,回顾历史分数。
如图5-5
图5-5:
历史回顾
(8)选择3,退出系统,如图5-6。
图5-6:
退出
5总结
对本次课程设计是制作一个试题库供小学生选题,我是通过栈来实现表达式求值的,起初对于表达式求值,我不知如何求值。
而后参考网上的我设置了运算符栈与数字栈来分别保存运算符和数字以及中间计算得到的结果。
通过这次课设,体会到每一个简单程序编写的困难以及自身的不足,对编程的不熟练,以及编写程序时产生的许多不必要的错误。
在创建磁盘文件时也有很多问题,磁盘的导入导出没实现。
所以将会加强自身的素质。
数据结构这门课感觉比较难,许多的功能都遍写不出来,我将会努力调试代码。
参考文献
[1]严蔚敏,吴伟民.数据结构(C语言版)[M].北京:
清华大学出版社,2007.
[2]刘汝佳.算法竞赛入门经典[M].北京:
清华大学出版社,2009.11.
[3](美)普拉达(Prata,S.)著,云颠工作室译.CPrimerPlus(第5版)中文版[M].北京:
人民邮电出版社,2005.2(2008.8重印).
[4]谭浩强.C语言程序设计[M].北京:
清华大学出版社,2006年.
[5]严蔚敏,吴伟民.数据结构题集(C语言版)[M].北京:
清华大学出版社,2007年.
[6]谢昕等编著,C程序设计(第二版),北京:
北京邮电大学出版社,2007.
附录
#include
#include
#include//对时间和日期操作
intN;//定义全局变量N,表示试题库试题数量
typedefstruct
{
chara[100];
intresult;
}Shiti;//试题数据类型
typedefstruct
{
int*base,*top;
intsize;
}Num;//数字栈
typedefstruct
{
char*base,*top;
intsize;
}Oper;//运算符栈
intNumInitStack(Num*S1)//构造数字栈
{
S1->base=(int*)malloc(100*sizeof(int));
if(!
S1->base)
{
printf("申请内存失败!
\n");
return0;
}
S1->top=S1->base;
S1->size=100;
return1;
}
intOperInitStack(Oper*S2)//构造运算符栈
{
S2->base=(char*)malloc(100*sizeof(char));
if(!
S2->base)
{
printf("申请内存失败!
\n");
return0;
}
S2->top=S2->base;
S2->size=100;
return1;
}
intNumGetTop(Num*S1)//得到数字栈栈顶元素
{
inte1;
if((*S1).top==(*S1).base)
return0;
e1=*((*S1).top-1);
returne1;
}
charOperGetTop(Oper*S2)//得到运算符栈栈顶元素
{
chare2;
if((*S2).top==(*S2).base)
return0;
e2=*((*S2).top-1);
returne2;
}
voidNumPush(Num*S1,inte1)//数字栈压栈
{
*(*S1).top++=e1;
}
voidOperPush(Oper*S2,chare2)//运算符栈压栈
{
*(*S2).top++=e2;
}
intNumPop(Num*S1)//数字栈弹栈
{
inte1;
if((*S1).top==(*S1).base)
return0;
e1=*--(*S1).top;
returne1;
}
charOperPop(Oper*S2)//运算符栈弹栈
{
chare2;
if((*S2).top==(*S2).base)
return0;
e2=*--(*S2).top;
returne2;
}
charPrecede(chara,charb)//判断运算符优先级
{
inti,j;
charTable[8][8]={{'','+','-','*','/','(',')','='},
{'+','>','>','<','<','<','>','>'},
{'-','>','>','<','<','<','>','>'},
{'*','>','>','>','>','<','>','>'},
{'/','>','>','>','>','<','>','>'},
{'(','<','<','<','<','<','=',''},
{')','>','>','>','>','','>','>'},
{'=','<','<','<','<','<','','='}};//优先级表格
for(i=0;i<8;i++)
if(Table[0][i]==a)//纵坐标寻找
break;
for(j=0;j<8;j++)//横坐标寻找
if(Table[j][0]==b)
break;
returnTable[j][i];
}
intOperate(inta,chartheta,intb)//计算二元表达式的值
{
intc;
if(theta=='+')
c=a+b;
elseif(theta=='-')
c=a-b;
elseif(theta=='*')
c=a*b;
else
c=a/b;
returnc;
}
intIsOper(charch)//判断字符ch是否为运算符
{
charptr[10]={'+','-','*','/','(',')','='};
inti;
for(i=0;i<7;i++)
{
if(ch==ptr[i])
return1;
}
return0;
}
intResult(chara[],Num*num,Oper*oper)//计算表达式的结果
{
chartheta;
intb,d,k=0,i=0,j=0,num2=0;
NumInitStack(num);//构造数字栈
OperInitStack(oper);//构造运算符栈
OperPush(oper,'=');//将“=”压到栈底
while(a[i]!
='='||OperGetTop(oper)!
='=')
{
//对表达式a进行计算
if(a[i]>='0'&&a[i]<='9')
{
//字符是数字
k++;
if(k<=j)
{
num2=a[i]-48;
i++;
}
if(k>j)
{
num2=num2*10+(a[i]-48);
k=j=0;
i++;
}
if(!
IsOper(a[i]))
k++;
if(k==j)//如果k等于j,说明下一个字符是运算符,即数字字符结束,压进数字栈
NumPush(num,num2);
}
elseif(IsOper(a[i]))
{
//字符是运算符
switch(Precede(a[i],OperGetTop(oper)))
{
//该运算符和栈顶运算符进行优先级比较并做相关处理
case'<':
OperPush(oper,a[i++]);
if(a[i]!
='('&&a[i]!
=')')
j++;
break;
case'=':
OperPop(oper);
i++;
break;
case'>':
theta=OperPop(oper);//运算符栈弹栈
d=NumPop(num);//数字栈弹栈
b=NumPop(num);
NumPush(num,Operate(b,theta,d));//计算结果并压栈
break;
}
}
}
return(NumGetTop(num));//返回最终计算结果
}
intBuildshitiku()//建立试题库
{
inti;
FILE*fp;
Shitit;
if(!
(fp=fopen("G:
\\shitiku.txt","w")))
{
printf("无法建立试题库文件!
\n");
return0;
}
printf("输入要建立的试题库的试题数目:
");
scanf("%d",&N);
fprintf(fp,"%d\n",N);
for(i=0;i{
printf("输入第%d道题目:
\n",i+1);
scanf("%s",t.a);
fprintf(fp,"%s\n",t.a);//将键盘输入的表达式写进文件
}
fclose(fp);
return1;
}
voidXuanti(intn,inta[])//随机选取n个题目,将题号保存在数组a中
{
srand((int)time(0));
inti,j,t;
a[0]=rand()%N;//产生0-N之间的随机数并记录
for(i=1;i{
t=rand()%N;
for(j=0;j
{
if(a[j]==t)
break;
}
if(j==i)
a[i]=t;
else
i--;
}
}
voidAvescore()//求平均成绩
{
FILE*fp1,*fp2;
intsum=0,i=0,s,a;
if(!
(fp1=fopen("G:
\\score.txt","r")))
{
printf("无法打开成绩信息文件!
\n");
exit(-1);
}
whi