c++课程设计--分数计算器
- 格式:doc
- 大小:483.00 KB
- 文档页数:15
C++课程设计报告题目:分数计算器年级:专业:通信工程姓名:指导老师:难度 B 级教师评语:1.程序功能介绍分数计算器及测试程序,具有对输入的运算进行“+,-,*,/,^”的功能2 .程序设计要求(1)完成计算器程序,对main函数的结构进行改进,要求有详细的菜单选项界面,用户不选择退出就可以反复运算。
(2)完善程序,改为多操作数基本四则运算,遇#停止。
(3)增加函数,完成四则混合运算,注意算法要考虑运算符的优先级,对应增加主菜单选项。
(4)增加语句使四则运算具有测试功能,即计算机能够自动出题,并要求用户计算,同时计算机判断用户计算的对错并打分,要求十题一个单元,每题一个运算符,参与运算的分子分母均为一位数,运算符包括加,减,乘,除及大于小于等逻辑运算符。
3. 基本数据结构含有整型变量,字符变量,实型变量,还定义了一个分数类;除此之外还有以下函数:1。
分数转换为小数;2。
分数转换为带分数;3。
实现简单计算的函数;4。
混合运算函数;5。
随机测试题函数;6。
清屏函数。
此外还多处运用了运算符的重载4. 程序运行结果界面1. 初始界面2.功能13.功能24.功能35.功能46.功能55. 课程设计遇到的技术问题与解决思路问题1:分数的表示解决办法:建立函数,分别置分母,分子,同时构造约分函数问题2:真分数的表示解决办法:构造函数,置整数部分和分数部分书本提供的源代码虽然较为完备,但也存在一些错误。
问题3:乘方的函数功能实现,书本提供的原有的类中重载的“^”运算符无法实现乘方运算解决办法:考虑到“^”运算符作为位运算符,不能按照双目运算符的重载格式进行重载,故,将用于代码内部的“^”运算符改为“%”双目运算符进行重载,进行重载运算,但对外输入输出,仍使用作为字符常量的^,解决了源代码中,分数运算乘方无法实现的问题。
fraction operator% (const fraction &base, int exp) //^运算符并非双目运算符//不可按照双目运算的方法重载,故修改为%,进行内部操作{fraction returnValue;returnValue.setnum(pow(base.numerator(), exp));returnValue.setden(pow(base.denominator(), exp));returnValue.simplify();return returnValue;}问题4:输出运算符<<重载不完善,因为对于函数参数分数首先进行了取绝对值运算,从而导致对于输出负分数的时候,无法正确输出。
解决办法:重新对重载函数进行改写,先判断原参数分数的正负,若为负,则先输出“-”后,再取绝对值,进行分子分母的分别输出操作。
而且原代码中对于分数正负的判断极为繁琐,故直接调用已经重载过的“>”进行判断。
ostream & operator<< (ostream &os, const fraction &f){if(f.decimal()<0) // This extremely complex and seeminglyos << "-"; // useless if statement tests to see if// fraction f is negative.现已修改fraction temp = f.absval();int numer = f.numerator();int denom = f.denominator();if(temp.numerator() == 0 || temp.denominator() == 1)os << temp.numerator();elseos << temp.numerator() << '/' << temp.denominator();return os;}问题5:考虑到人性化的操作,实现用户不选择退出,就可以实现持续的操作,故设计了一系列的多级菜单,从而实现用户结束一个操作之后,可以选择继续本操作。
如果不继续操作,则可以选择回到上一个菜单,或者回到主菜单,或者直接退出。
但是为了实现这一系列的选择操作,可是费了一番功夫。
解决办法:(1)首先对于是否继续的选择操作,定义的字符型变量ch,为了防止变量名重复,主菜单对应的每一个操作,在ch后都设置了不同的数字,与主菜单后的每个操作前数字一致。
利用if语句进行判断。
如果,用户选择不继续本次操作,那么就输出另一个选择菜单,选择是返回上一级的菜单还是直接退出程序,并且具备了一定的异常处理功能,如果输入错误的指令,则会显示出来,要求用户重新输入代码,为了大大简化程序,此功能利用goto语句实现。
loop1:if(ch1=='N'||ch1=='n'){cout<<"1.返回主菜单;2,直接退出程序\n";char ch11;cin>>ch11;switch(ch11){case'1':main();case'2':exit(0);default:{cout<<"输入指令不正确,请重新输入!\n";goto loop1;}}}(2)关于实现在函数执行过程中返回主函数,可谓大费周章了,首先通过查资料得知,在main()内部返回主函数开头,可以在语句中直接使用main();语句。
但是,在外部定义的函数中,不能使用该语句,否则将出现error C2065: 'main' : undeclared identifiererror C2373: 'main' : redefinition; different type modifiers 这两个语法错误,为了解决该问题,想到了使用goto语句,但是该语句无法在函数间跳跃,故而只得作罢。
然后又想到利用返回值进行判断,但是,每次判断是,则要执行被调函数,再一次运行一次混合运算函数,或者是测试函数,显然是不可以的。
最终,查了一些资料,获得启发。
无返回值类型的函数,通过return;语句可以直接跳出该函数。
于是定义了一个全局变量judgement,当遭遇需要返回主菜单时,便将judgement进行赋值为1,随后跳出,对judgement进行判断,从而判断是否返回主菜单,如是,则配合主函数中的main()返回到主函数开头。
(3)在随后要讲到的异常处理部分,当检测到被除数为0的时候,则弹出提示消息,并且可以选择是否重新输入该数字,或者直接返回上一级菜单。
if(f2==0){cout<<"被除数不能为0!!\n1.重新输入该数。
2.返回主菜单。
\n";int k4;cin>>k4;if(k4==1){cin>>f2;goto loopsmall1;}else {judgement=1;return;} //由此实现由外部函数直接回到主函数头部}if(judgement==1)main();问题6:混合运算的核心问题即是优先级的控制;解决办法:为了实现运算的优先级,则需要综合判断前后的两个运算符,首先算出优先级较高的运算符两边前推进,则定义了3个分数类的对象result ,f1,f2.以及两个代表前后运算符的字符型变量op1,op2。
并通过对其不断赋值,如op1=op2,实现运算的推进.具体操作通过switch的嵌套实现。
过程及其繁琐,而且一旦语句出现偏差,极易出现难以发现的运行错误,即最终计算结果不正确。
一下为函数的定义://==========================================混合运算====================================================================void complex(){fraction f1,f2,result;char op1,op2;cout<<"ATTENTION:为保证计算的准确性,若需要输入整数X进行计算,请将该整数以X/1的形式进行输入!!!";cout<<"请依次输入分数(整数)和运算符,并以#结束~\n";op1=' ';cin>>f1>>op2;while(op2!='#'){judgement=0;cin>>f2;switch(op1){case' ':result=f1;f1=f2;op1=op2;break;case'+':{switch(op2){case'+':case'-':result=result+f1;f1=f2;op1=op2;break;//case'*':f1=f1*f2;break;loopsmall1: case'/':{if(f2==0){cout<<"被除数不能为0!!\n1.重新输入该数。
2.返回主菜单。
\n";int k4;cin>>k4;if(k4==1){cin>>f2;goto loopsmall1;}else {judgement=1;return;}// 由此实现由外部函数直接回到主函数头部 1111}f1=f1/f2;break;//op1=op2}}break;case'-':{switch(op2){case'+':case'-':result=result-f1;f1=f2;op1=op2;break;//case'*':f1=f1*f2;break;loopsmall2: case'/':{if(f2==0){cout<<"被除数不能为0!!\n1.重新输入该数。
2.返回主菜单。
";int k4;cin>>k4;if(k4==1){cin>>f2;goto loopsmall2;}else {judgement=1;return;} //1111}f1=f1/f2;break;}}}break;case'*':result=result*f1;f1=f2;op1=op2;break;//case'/':{if(f1==0){ cout<<"倒数第二个数为0,不能作为被除数!!!现在返回主菜单\n";judgement=1;return; //11111}result=result/f1;f1=f2;op1=op2;break;//}}//switch(op1) endcin>>op2;}switch(op1){case'+':cout<<"结果为:"<<result+f1<<endl;break;case'-':cout<<"结果为:"<<result-f1<<endl;break;case'*':cout<<"结果为:"<<result*f1<<endl;break;loopsmall3: case'/':if(f1==0)cout<<"被除数不能为0!!\n1.重新输入该数。