迷你计算器说明书.docx
《迷你计算器说明书.docx》由会员分享,可在线阅读,更多相关《迷你计算器说明书.docx(28页珍藏版)》请在冰豆网上搜索。
迷你计算器说明书
*******************
实践教学
*******************
兰州理工大学
计算机与通信学院
2012年春季学期
算法与数据结构课程设计
题目:
迷你计算器设计
专业班级:
计算机科学与技术
姓名:
学号:
指导教师:
成绩:
目录
摘要1
前言2
正文3
1.采用类c语言定义相关的数据类型3
2.各模块的伪码算法5
3.函数的调用关系图10
4.调试分析10
5.测试结果11
总结14
参考文献15
致谢16
附件:
源程序代码(带注释)17
摘要
目前,计算器应用很广泛,本程序是关于这方面的,其主要功能是进行简单的四则运算,其特点之一是支持带括号的四则运算;二是用到栈的一些相关操作,不但对操作有提示,还对与异常输入信息报错。
通过该题目的设计过程,可以加深理解线性表及栈的逻辑结构、存储结构,掌握线性表及栈上基本运算的实现,进一步理解和熟练掌握课本中所学的各种数据结构,学会如何把学到的知识用于解决实际问题,培养学生的动手能力。
堆栈是十分重要的数据结构,在操作系统的作业调度、进程调度和数据库系统事物管理中广泛应用了队列技术。
栈是一种限定性线性表,它是一类操作受限制的特殊线性表,其特殊性在于限制线性表插入和删除等操作的位置。
关键词:
堆栈;初始化栈;入栈;出栈。
前言
很多涉及计算器程序的的算法都是以栈的相关操作为基础,通过计算器的设计,有利于在学习中更好的理解栈及其相关的操作。
通过对计算器计算过程演示,看到了到它的一些性能及相关优势。
我们在写程序时,大框架已成的情况下,仍然发现有些错误很难找到,对于这样的问题,可以利用计算机纠错功能,先运行,再根据题提示修改和完善程序。
在计算器用到的算法中,C语言算法可读性很强,一方面,是因为c语言是高级语言,是面向程序员的语言,二是C语言的功能是很完备的,可以达到事半功倍的效果,和其他语言相比量是比较少。
栈的应用使该程序更出色。
通过该课程设计,运用所学知识,能上机解决一些实际问题,了解并初步掌握设计、实现较大程序的完整过程,包括系统分析、编码设计、系统集成、以及调试分析,熟练掌握数据结构的选择、设计、实现以及操作方法,为进一步的应用开发打好基础。
正文
1.采用类c语言定义相关的数据类型
(1)/*定义堆栈*/
typedefstruct{
doubledata[M];
inttop;
}Stack;
(2)/*初始化堆栈*/
InitStack(Stack*s)
{
s->top=0;
}
(3)/*判断栈是否为空*/
intStEmpty(Stack*s)
{
if(s->top==0)
{
return1;
}
else
{
return0;
}
}
(4)/*入栈操作*/
StPush(Stack*s,doublex)
{
if(s->top==M)
{
printf("Thestackisoverflow!
");
}
else
{
s->top=s->top+1;
s->data[s->top]=x;
}
}
(5)/*出栈操作*/
doubleStPop(Stack*s)
{
doublet;
if(!
StEmpty(s))
{
t=s->data[s->top];
s->top=s->top-1;
}
else
{
printf("StPop:
Thestackisempty!
");
t=NULL;
}
returnt;
}
2.各模块的伪码算法
(1)/*定义堆栈*/
typedefstruct{
doubledata[M];
inttop;
}Stack;
(2)/*初始化堆栈*/
InitStack(Stack*s)
{
s->top=0;
}
(3)/*判断栈是否为空*/
intStEmpty(Stack*s)
{
if(s->top==0)
{
return1;
}
else
{
return0;
}
}
(4)/*入栈操作*/
StPush(Stack*s,doublex)
{
if(s->top==M)
{
printf("Thestackisoverflow!
");
}
else
{
s->top=s->top+1;
s->data[s->top]=x;
}
}
(5)/*出栈操作*/
doubleStPop(Stack*s)
{
doublet;
if(!
StEmpty(s))
{
t=s->data[s->top];
s->top=s->top-1;
}
else
{
printf("StPop:
Thestackisempty!
");
t=NULL;
}
returnt;
}
(6)/*获取栈顶元素*/
doubleStGetTop(Stack*s)
{
doublet;
if(!
StEmpty(s))
{
t=s->data[s->top];
}
else
{
printf("StGeTop:
Thestackisempty!
");
t=NULL;
}
returnt;
}
(7)/*将数字字符转换成整形*/
intChrTransferint(charc)
{
intn;
switch(c)
{
case'0':
n=0;break;
case'1':
n=1;break;
case'2':
n=2;break;
case'3':
n=3;break;
case'4':
n=4;break;
case'5':
n=5;break;
case'6':
n=6;break;
case'7':
n=7;break;
case'8':
n=8;break;
case'9':
n=9;break;
}
returnn;
}
(8)/*获取两个操作符之间数字字符的个数,返回的是最后一个数字字符的位置*/
intGetNumsize(charstr[],intn1)
{
intn2=n1;
while(isdigit(str[n2])||(str[n2])==46)/*isdigit()判断是否数字字符*/
{
n2=n2+1;
}
returnn2;
}
(9)/*判断上个函数中获得的数字字符串中是否包含小数点,并返回它的位置,不包含,返回-1*/
intIsIncludepoint(charstr[],intn1,intn2)
{
intn3=-1;
inti;
for(i=n1;i<=n2;i++)
{
if(str[i]=='.')
{
n3=i;
break;
}
}
returnn3;
}
(10)/*将数字字符转换成数值*/
doubleTransfer(charstr[],intn1,intn2,intn3)
{
doubledata=0;
inti,ct;
if(n3<0)
{
for(i=n2;i>=n1;i--)
{
ct=ChrTransferint(str[i]);
data=data+ct*pow(10,n2-i);/*pow(x,y)计算x的y次方的值*/
}
}
else
{
for(i=n3-1;i>=n1;i--)
{
ct=ChrTransferint(str[i]);
data=data+ct*pow(10,n3-1-i);/*pow(x,y)计算x的y次方的值*/
}
for(i=n3+1;i<=n2;i++)
{
ct=ChrTransferint(str[i]);
data=data+ct*pow(0.1,i-n3);/*pow(x,y)计算x的y次方的值*/
}
}
returndata;
}
3.函数的调用关系图
4.调试分析
a、调试中遇到的问题及对问题的解决方法
本程序一开始面临精确度不高的问题,具体说就是它只能计算整数,对于小数它会报告输入错误,这种性能缺陷是致命的,打个比方,就像一个大个子,长了两只很短的胳膊。
对此,我定义操作数类型时,将原来的int型改为float型和double型。
b、算法的时间复杂度和空间复杂度
时间复杂度
栈存储为0(n)
空间复杂度
整个程序转为C可执行后整体的空间复杂度为224KB。
5.测试结果
1)运行简单的加减运算,运行界面如下:
2)运行简单的乘除运算,运行界面如下:
3)运行简单混合运算操作,显示如下:
4)运行复杂混合运算操作,显示如下:
5)运行稍复杂的混合运算,界面显示如下:
总结
三周的课程设计,对我来说是一个考验,毕竟这是我入学以来挑战性最高也最有技术性的一次独立的设计性课题。
在这次课程设计中我对整个程序主体结构的设计、界面的设计、部分算法功能代码的编写还算是相当顺利的,因为很多程序段、函数的定义和调用及用法在平时的学习中已有所掌握,并且在以往学习的过程中我们对C语言编程中的常用语句、循环结构、过程也已熟知。
现在我所遇到的最大难题是数据库的编辑和代码的编写,而计算器用到数据库是为了进一步方便数据的计算。
毕竟我们原本对数据库的了解就不多,但是在学习设计的过程中我发现许多数据结构中的算法都是有一定的相似之处的,我主要查看了线性表及栈的逻辑结构、存储结构,线性表及栈上的基本运算。
加上老师和同学们的帮助,我才能够在短时间的期限内可以勉强完成设计任务。
通过该课程设计,能运用所学知识,能上机解决一些实际问题,了解并初步掌握设计、实现较大程序的完整过程,包括系统分析、编码设计、系统集成、以及调试分析,熟练掌握数据结构的选择、设计、实现以及操作方法,为进一步的应用开发打好基础。
本次课程设计我们从一开始的选题到现在的设计结束,前前后后将近半个月时间。
在这期间,我从C语言课本和数据结构课本上熟悉和巩固了许多基本知识,通过这次课程设计,我不仅对课本的基本知识有了一定的掌握,还对其他方面的知识也有所了解,这些将为我以后的课程设计打下扎实的基础,使我受益匪浅!
参考文献
1.严蔚敏,吴伟民.《数据结构(C语言版)》.清华大学出版社.
2.严蔚敏,吴伟民.《数据结构题集(C语言版)》.清华大学出版社.
3.《DATASTRUCTUREWITHC++》.WilliamFord,WilliamTopp.清华大学出版社(影印版).
4.谭浩强.《c语言程序设计》.清华大学出版社.
5.数据结构与算法分析(Java版),APracticalIntroductiontoDataStructuresandAlgorithmAnalysisJavaEditionCliffordA.Shaffer,张铭,刘晓丹译 电子工业出版社2001年1月
致谢
本次课程设计能够顺利完成首先感谢我的指导老师年福忠年老师和教我算法与数据结构的张永张老师,他们在我的课程设计过程中提出了指导性的方案和架构,并指引我阅读相关的资料和书籍,使我在不熟悉的领域中仍能迅速掌握新的技术。
第二,我要感谢教我算法与数据结构的张永张老师和C语言余勇余老师在以往的基础课学习中为我打下良好的基础,这是我这次课程设计能够顺利完成的前提。
我的同学在设计过程中对我的帮助和完成设计后对程序的测试,没有他们,也许就难以发现一些潜在的错误,在此,也谢谢他们!
。
附件:
源程序代码(带注释)
#include
#include
#include
#include
#include
#defineM40
/*定义堆栈*/
typedefstruct{
doubledata[M];
inttop;
}Stack;
/*初始化堆栈*/
InitStack(Stack*s)
{
s->top=0;
}
/*判断栈是否为空*/
intStEmpty(Stack*s)
{
if(s->top==0)
{
return1;
}
else
{
return0;
}
}
/*入栈操作*/
StPush(Stack*s,doublex)
{
if(s->top==M)
{
printf("Thestackisoverflow!
\n");
}
else
{
s->top=s->top+1;
s->data[s->top]=x;
}
}
/*出栈操作*/
doubleStPop(Stack*s)
{
doublet;
if(!
StEmpty(s))
{
t=s->data[s->top];
s->top=s->top-1;
}
else
{
printf("StPop:
Thestackisempty!
\n");
t=NULL;
}
returnt;
}
/*获取栈顶元素*/
doubleStGetTop(Stack*s)
{
doublet;
if(!
StEmpty(s))
{
t=s->data[s->top];
}
else
{
printf("StGeTop:
Thestackisempty!
\n");
t=NULL;
}
returnt;
}
/*将数字字符转换成整形*/
intChrTransferint(charc)
{
intn;
switch(c)
{
case'0':
n=0;break;
case'1':
n=1;break;
case'2':
n=2;break;
case'3':
n=3;break;
case'4':
n=4;break;
case'5':
n=5;break;
case'6':
n=6;break;
case'7':
n=7;break;
case'8':
n=8;break;
case'9':
n=9;break;
}
returnn;
}
/*获取两个操作符之间数字字符的个数,返回的是最后一个数字字符的位置*/
intGetNumsize(charstr[],intn1)
{
intn2=n1;
while(isdigit(str[n2])||(str[n2])==46)/*isdigit()判断是否数字字符*/
{
n2=n2+1;
}
returnn2;
}
/*判断上个函数中获得的数字字符串中是否包含小数点,并返回它的位置,不包含,返回-1*/
intIsIncludepoint(charstr[],intn1,intn2)
{
intn3=-1;
inti;
for(i=n1;i<=n2;i++)
{
if(str[i]=='.')
{
n3=i;
break;
}
}
returnn3;
}
/*将数字字符转换成数值*/
doubleTransfer(charstr[],intn1,intn2,intn3)
{
doubledata=0;
inti,ct;
if(n3<0)
{
for(i=n2;i>=n1;i--)
{
ct=ChrTransferint(str[i]);
data=data+ct*pow(10,n2-i);/*pow(x,y)计算x的y次方的值*/
}
}
else
{
for(i=n3-1;i>=n1;i--)
{
ct=ChrTransferint(str[i]);
data=data+ct*pow(10,n3-1-i);/*pow(x,y)计算x的y次方的值*/
}
for(i=n3+1;i<=n2;i++)
{
ct=ChrTransferint(str[i]);
data=data+ct*pow(0.1,i-n3);/*pow(x,y)计算x的y次方的值*/
}
}
returndata;
}
/*主程序*/
main()
{
charstr[M],c;
chara;
intn,p1,p2,p3;/*n为字符串长度,p1,p2,p3分别为数字字符起始位置,结束位置,和小数点位置*/
doubledata;/*存放转换后的数值*/
inti=0;
Stack*so=(Stack*)malloc(sizeof(Stack));/*存储操作符'(':
1,'+':
2,'-':
3,'*':
4,'/':
5字符'),='不压栈*/
Stack*sd=(Stack*)malloc(sizeof(Stack));/*存储操作数*/
InitStack(so);
InitStack(sd);
printf("\n\n\t=============欢迎使用迷你计算器=============\n\n");
printf("\nPleaseinputformula(format:
(1+2)*1.2/4=):
\n");
n=0;
while((a=getchar())!
='\n')
{
str[n]=a;
n++;
}
while(i{
charc;
c=str[i];
if(c=='(')
{/*c若是'('直接入栈so,i++*/
StPush(so,1);
i++;
}
elseif(isdigit(c))
{
p1=i;/*c若是数字字符,一并将后面的连续数字字符转换为数值并压栈到sd,并把i设为后面的*/
p2=GetNumsize(str,p1);
p3=IsIncludepoint(str,p1,p2-1);/*第一个非数字字符的位置*/
data=Transfer(str,p1,p2-1,p3);
StPush(sd,data);
i=p2;
}
elseif(c=='+')
{
StPush(so,2);/*c若是'+'直接入栈so,i++*/
i++;
}
elseif(c=='-')
{
StPush(so,3);/*c若是'-'直接入栈so,i++*/
i++;
}
elseif(c=='*')
{
if(str[i+1]=='(')/*c若是'*'它后面的字符是否为'(',若是直接将'*'压栈so,*/
{
StPush(so,4);
i++;
}
else
{
doublet1,t2,t3;/*若不是,为数字字符,将后面的连续数字字符一并转换成数值t2,sd出栈给t1,将t3=t2*t1压栈到sd*/
t1=StPop(sd);/*操作符'*'不压栈so*/
p1=i+1;
p2=GetNumsize(str,p1);
p3=IsIncludepoint(str,p1,p2-1);
t2=Transfer(str,p1,p2-1,p3);
t3=t1*t2;
StPush(sd,t3);
i=p2;
}
}
elseif(c=='/')
{
if(str[i+1]=='(')
{
StPush(so,5);
i++;
}
else
{
doublet1,t2,t3;
t1=StPop(sd);/*c是'/'同'*'*/
p1=i+1;
p2=GetNumsize(str,p1);
p3=IsIncludepoint(str,p1,p2-1);
t2=Transfer(str,p1,p2-1,p3);
t3=t1/t2;
StPush(sd,t3);
i=p2;
}
}
elseif(c==')')
{
doublet1,t2,t3;
intp;
while((p=StPop(so))!
=1&&!
StEmpty(so))/*c若是')',出栈so,判断是'+'或'-',出栈sd两个操作数,进行加减运算*/
{/*直到StPop=='('*/
t1=StPop(sd);
t2=StPop(sd);
if(p==2)
{
t3=t2+t1;
StPush(sd,t3);
}
elseif(p==3)
{
t3=t2-t1;
StPush(sd,t3);
}
}
if(StGetTop(so)==4)/*然后判断so栈顶是否为'*'或者'/'*/
{
StPop(so);
t1=StPop(sd);/*为'*'出栈so,出栈sd获得2个操作数,进行乘法操作*/
t2=StPop(sd);
t3=t2*t1;
StPush(sd,t3);
}
elseif(StGetTop(so)==5)
{
StPop(so);
t1=StPop(sd);/*为'/'出栈so,出栈sd获得2个操作数,进行除法操作*/
t2=StPop(sd);
t3=t2/t1;
StPush(sd,t3);
}
i++;
}
elseif(c=='=')
{
doublet1,t2,t3;/*c若是'=',这是so内只有加减号,出栈so到p,sd到t1,t2*/
intp;
while(!
StEmpty(so))
{
t1=StPop(sd);
t2=StPop(sd);
p=StPop(so);
if(p==2)
{
t3=t2+t1;/*p=='+',加法运算,并将结果t3压栈sd*/
S