资源描述
C语言课程设计-简易计算器xxxx大学信息科学与工程学院课程设计报告班 级: 通信工程一班 姓名 (学号): xxx 实验项目名称: 简易计算器 实验室(中心): 信息科学与工程学院信息技术实验室 指 导 教 师 : xxx 实验完成时间: 2012 年 6 月 19 日 目录一:课程设计题目3二:功能描述3三:概要设计4四:详细设计5五:测试结果及存在的问题9六:课程设计心得体会12七:附录12序号项目标准评分1系统演示(功能)(50%)按要求完成系统功能且界面友好容错能力强(45-50)按要求完成系统功能界面一般有较好的容错能力(40-44)基本完成系统功能有一定的容错能力(35-39)基本完成系统功能(30-34分)未完成系统功能或他人代做或抄袭(15)2课程设计说明书(50%)课程设计书各项目认真填写,具有清晰的设计思路及软件测试结果分析(45-50)课程设计书各项目认真填写,具有较为清晰的设计思路并对软件测试结果进行了较为清晰的分析(40-44)课程设计书各项目认真填写,设计思路正确(35-39)课程设计书进行为较为认真的填写(30-34)课程设计书有未完成项或各项填写不属实或他人代做或抄袭(15)教师签字总分一、题目: 简易计算器设计二、功能描述: 此简易计算器根据算符优先算法原则可以计算由“+,-,*,/,(,)”组成的任意算术表达式的值。其中此程序中包含对负数和字符数据转换功能。如:-9+(2+3)*9/8-5)/(-3);三、概要设计:根据算符优先算法设计将函数功能模块分布如下: 利用结构体数组中脚码的变换达到符号和数据进栈和出栈的目的。算符优先算法计算表达式的值 定义运算符栈和数据栈及各个函数的类型和数据的类型(自定义完成) 功能:完成栈的定义和初始化及函数的类型定义及运算符 集合定义. 字符型数据表达式的输入并对负数处理以符合算法规则(Translate函数完成) 功能:完成负数转换成(0-负数)形 N 式以便数据读入 (Translate). 判断表达式是否正确(Can函数完成) 功能:完成判断表达式是否符合 一般计算表达式规则(Can). Y运算符和数据的进栈和出栈(自定义函数完成) 功能:完成运算符和数据的进栈 和出栈. 功能:完成数据算符优先级比较(Precede函数完成)字符型数据转换成浮点型数据(Getdouble函数完成) 转换和运算符 比较.数据运算的过程及输出(Operate和EvaluateExpression函数完成) 功能:完成函数调用以完成 数值计算.四、详细设计:各功能模块的实现过程如下: 1:栈的应用:通过运用结构体数组中top值的改变来达到数据进栈和出栈的目的,而栈的初始化只需将top的初始值赋为-1即可 ; 2:表达式负数的处理(由Translate函数完成): Y N Y N N Y结束返回新的数组sit?(t为数组长度)i+1之后元素向后移一位,si+1=0si=(且si+1=-S数组首位加0S0=-?读入字符串数组(s)开始 算法说明:函数中,先扫描数组,若s0=-,则将数组的所有元素向后 移一位且首位赋值为0,若数组首位之后含有形如(-5)则将负号及其以后的元素全向后移一位且负号位置赋值为0,然后返回新的数组; i=i+1,t=t+1 3:表达式正误的判断(由Can函数完成): 函数说明: 函数中将错误归为几类:括号的完整性、运算符后的数据类型、除号后的数据不能为0、小数点及运算符不能多个在一起、右括号后的数据必须为运算符或结束标志;函数通过p和s记录对这些错误的判断,并返回结果;4:进栈和出栈: 说明:运算符和数据的进栈是通过给结构体数组赋值并增加top的值来记录栈的栈顶元素的位置 以便取用;出栈是使top的减1后的那个数组中的数据作为新栈的栈顶元素,并返回栈顶元素.即实质上是通过改变数组的位置来达到进栈出栈; 5:字符串数据转换成浮点型数据(由Getdouble函数完成): 函数说明: 从字符数组的运算符开始扫描,直到遇到下一个运算符结束,然后将这两个运算符间的字符记录在数组S中,再用库函数atof将字符数据转换成浮点型数据并返回数据和数组a中新的元素的起点(即扫描到的第二个运算符); 6:算符优先级的比较: 函数说明: 此函数是记录运算符栈的栈顶元素在运算符集合中的位置与读入运算符在运算符集合中的位置,将这两个值作为运算符优先级表数组的脚码,然后返回这个元素所代表的字符; 7:算符优先算法求表达式的值的核心算法: 说明:此函数中使用两个工作栈,一个是OPTR,用以寄存运算符;另一个是OPND,用以寄存浮点型数据。基本思想是:首先置数栈为空栈,表达式的起始符号为#算符栈的栈底元素;然后依次读入表达式中的每一个字符,若为数则进OPND数栈,若为运算符则和OPTR算符栈的栈顶运算符比较优先级后,如果栈顶算符优先级低,则此算符进栈并返回新的栈顶算符;如果栈顶算符优先级高,则取算符栈栈顶算符theta并删除此算符,同时去数栈的最上面的两个数a和b并删除这两个数,作a theta b运算并将结果进数栈;如果两个算符优先级相同,则删除算符栈顶算符并返回新的栈顶算符。直到整个表达式求值完毕(即OPTR的栈顶算符和当前读入的字符均为#时求值完毕)。 程序框图如下: Y N Y 开始定义并初始化栈ch=算符栈顶元素,k=0ch!=# | sk!=#sk是算符?ch和算符栈顶元素优先级算符进栈删除栈顶元素去算符栈顶元素(theta)字符串转换为浮点型数据删除theta并返回新栈顶元素取数栈栈顶的两元素a,b删除数栈的最上面的两元素结果进数栈计算a(theta)b的值k=k+1ch=算符栈顶元素x=数栈顶元素输出x的值结束五、测试结果及存在的问题: 1:系统运行效果: 输入界面: 正确的计算: 再计算界面错误报告: 修正再计算: 2:存在的不足及预期的解决办法:不足之处:计算器的操作界面不是很美观;而且程序循环使用不能在指定的位置退出;目前只能用于计算+、-、*、/ 四则运算; 预期的解决办法 : 查询资料学习了解操作界面的制作方法及需要的技巧; 查询相关资料了解学习有关处理字符数组赋值的相关问题 (即处理字符数组赋值只取到预定的位置); 学习了解相关的库函数的功能以增加计算器的计算功能 (如计算器的次方、开方、等的运算) . 六、课程设计心得体会:心得体会: 我对编程是有很浓厚兴趣的。在编程的过程中,我深深地体会到力不从心有些知识没能深入地理解和掌握以及VC+的许多功能没能探索和了解使我编程时有好多的思想运用不上(如设计一个美观的操作界面)。另外,我也感受到了数据结构的重要性,有了结构才能将好的思想付诸实践。同时经过查询资料了解到栈由多种运用方法,其中包括栈的顺序存储结构和链式存储结构,栈是计算表达式的经典应用。数据结构中的许多结构都是很经典思想,只有把编程语言和数据结构都熟练掌握的情况下,才能做出一些很好的作品。在编程过程中,虽然有时候是很发闷的,尤其是程序无错但结果不对,但是在完成一个完整的程序时所带来的喜悦是其它事情所不能替代的。我很喜欢编程,即使我的知识和能力有限,但我相信经过努力,一切皆有可能。七、附录: 程序源代码如下:#include #include #include /算符优先级表char First77= /+,-,*,/,(,),# /*+*/ , /*-*/ , /*/ , /*/*/ , /*(*/ , , /*#*/ ,top=-1;/初始化数据站函数void InitStack_D(OPND_Stack *a)a-top=-1;/运算符进栈函数void Push_R(OPTR_Stack *a,char b)a-top+;a-dataa-top=b;/数据进栈函数void Push_D(OPND_Stack *a,double b)a-top+;a-dataa-top=b;/取运算符栈顶符函数void GetTop_R(OPTR_Stack *a,char *b)*b=a-dataa-top;/取数据栈顶数函数void GetTop_D(OPND_Stack *a,double *b)*b=a-dataa-top;/判断数据是否为运算符函数int In(char a,char *s)for(int i=0;i7;i+)if(a=si)return 1;return 0;/算符优先级判断函数char Precede(char a,char b)int m,n;for(int i=0;itop-;*b=a-dataa-top;/取数据站的栈顶元素,并从栈中删除此元素void Pop_D(OPND_Stack *a,double *b)*b=a-dataa-top;a-top-;/二元运算函数double Operate(double a,char theta,double b)switch(theta)case+:return a+b;case-:return a-b;case*:return a*b;case/:return a/b;default:return 0;/将字符串转换成浮点型数据double Getdouble(char *a,int *b)double x;char s50;int m=0,n;n=strlen(a);for(int i=*b;in;i+)if(In(ai,OP)=1)m=i;break;for(i=*b;im;i+)si-*b=ai;strcat(s,0);x=atof(s);*b=m;return x;/算符优先算法求值核心函数double EvaluateExpression(char *s)OPND_Stack OPND;OPTR_Stack OPTR;char ch,theta;double x,a,b;int k=0;strcat(s,#);InitStack_R(&OPTR);Push_R(&OPTR,#);InitStack_D(&OPND);GetTop_R(&OPTR,&ch);while(sk!=#|ch!=#)if(In(sk,OP)=0)x=Getdouble(s,&k);Push_D(&OPND,x);elseswitch(Precede(ch,sk)case:GetTop_R(&OPTR,&theta);Pop_R(&OPTR,&ch); Pop_D(&OPND,&b);Pop_D(&OPND,&a);Push_D(&OPND,Operate(a,theta,b);break;GetTop_R(&OPTR,&ch);GetTop_D(&OPND,&x);return x;InitStack_R(&OPTR);Push_R(&OPTR,#);InitStack_D(&OPND);/判断表达式是否输入正确.int Can(char a,int n) int p=0,s=0,t=0;for(int i=0;in;i+)if(ai=(|ai=)p+;if(ai=+|ai=-|ai=*|ai=/)&(ai+19)s+;if(ai=/&ai+1=0)s+;if(ai=(&(ai=+|ai=-|ai=*|ai=/)|(ai=)&ai+1=()s+;if(ai=)&ai+1!=0&(ai+1!=+&ai+1!=-&ai+1!=*&ai+1!=/)s+;if(ai=.&ai+1=.)s+;if(p%2=0&s=0) return 0;return 1;/负数转换函数void Translate(char *s)char b80;int k,t;if(s0=-)b0=0;b1=0;strcat(b,s);strcpy(s,b);t=strlen(s);k=t;for(int i=0;i=k;j-) sj=sj-1; sk=0; st+1=0; t=strlen(s); k=t;/主函数void main() system(color B0);char a80;int m;char b80;printf(=简易计算器=n);printf(四则运算.如:-1+(2+3)*9/(-2)-6.n请输入一个表达式:n);while(1)gets(a);strcpy(b,a);Translate(a);while(1)int p;m=strlen(a);p=Can(a,m);if(p=0) break;system(color F4);printf(输入错误.请从新输入表达式:n);gets(a);strcpy(b,a);Translate(a);system(color B0);printf(=*=*=*=*=*=*表达式结果=*=*=*=*=*=*n);printf(该表达式的结果为:n%s=%-10.3lfn,b,EvaluateExpression(a);printf(=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*n);printf(继续使用四则运算.如:-1+(2+3)*9/(-2)-6.n请再输入一个表达式:n);通信工程11级一班 16 / 17 刘 秀
展开阅读全文