c++课程设计分数计算器.docx

上传人:b****5 文档编号:28416924 上传时间:2023-07-13 格式:DOCX 页数:19 大小:413.89KB
下载 相关 举报
c++课程设计分数计算器.docx_第1页
第1页 / 共19页
c++课程设计分数计算器.docx_第2页
第2页 / 共19页
c++课程设计分数计算器.docx_第3页
第3页 / 共19页
c++课程设计分数计算器.docx_第4页
第4页 / 共19页
c++课程设计分数计算器.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

c++课程设计分数计算器.docx

《c++课程设计分数计算器.docx》由会员分享,可在线阅读,更多相关《c++课程设计分数计算器.docx(19页珍藏版)》请在冰豆网上搜索。

c++课程设计分数计算器.docx

c++课程设计分数计算器

 

C++课程设计报告

 

题目:

分数计算器

年级:

专业:

通信工程

姓名:

指导老师:

难度B级

教师评语:

 

 

1.程序功能介绍

分数计算器及测试程序,具有对输入的运算进行“+,-,*,/,^”的功能

2.程序设计要求

(1)完成计算器程序,对main函数的结构进行改进,要求有详细的菜单选项界面,用户不选择退出就可以反复运算。

(2)完善程序,改为多操作数基本四则运算,遇#停止。

(3)增加函数,完成四则混合运算,注意算法要考虑运算符的优先级,对应增加主菜单选项。

(4)增加语句使四则运算具有测试功能,即计算机能够自动出题,并要求用户计算,同时计算机判断用户计算的对错并打分,要求十题一个单元,每题一个运算符,参与运算的分子分母均为一位数,运算符包括加,减,乘,除及大于小于等逻辑运算符。

3.基本数据结构

含有整型变量,字符变量,实型变量,还定义了一个分数类;

除此之外还有以下函数:

1。

分数转换为小数;2。

分数转换为带分数;3。

实现简单计算的函数;4。

混合运算函数;5。

随机测试题函数;6。

清屏函数。

此外还多处运用了运算符的重载

4.程序运行结果界面

1.初始界面

2.功能1

3.功能2

4.功能3

5.功能4

6.功能5

 

5.课程设计遇到的技术问题与解决思路

问题1:

分数的表示

解决办法:

建立函数,分别置分母,分子,同时构造约分函数

问题2:

真分数的表示

解决办法:

构造函数,置整数部分和分数部分

书本提供的源代码虽然较为完备,但也存在一些错误。

问题3:

乘方的函数功能实现,书本提供的原有的类中重载的“^”运算符无法实现乘方运算

解决办法:

考虑到“^”运算符作为位运算符,不能按照双目运算符的重载格式进行重载,故,将用于代码内部的“^”运算符改为“%”双目运算符进行重载,进行重载运算,但对外输入输出,仍使用作为字符常量的^,解决了源代码中,分数运算乘方无法实现的问题。

fractionoperator%(constfraction&base,intexp)//^运算符并非双目运算符

//不可按照双目运算的方法重载,故修改为%,进行内部操作

{

fractionreturnValue;

returnValue.setnum(pow(base.numerator(),exp));

returnValue.setden(pow(base.denominator(),exp));

returnValue.simplify();

returnreturnValue;

}

问题4:

输出运算符<<重载不完善,因为对于函数参数分数首先进行了取绝对值运算,从而导致对于输出负分数的时候,无法正确输出。

解决办法:

重新对重载函数进行改写,先判断原参数分数的正负,若为负,则先输出“-”后,再取绝对值,进行分子分母的分别输出操作。

而且原代码中对于分数正负的判断极为繁琐,故直接调用已经重载过的“>”进行判断。

ostream&operator<<(ostream&os,constfraction&f)

{

if(f.decimal()<0)//Thisextremelycomplexandseemingly

os<<"-";//uselessifstatementteststoseeif

//fractionfisnegative.现已修改

fractiontemp=f.absval();

intnumer=f.numerator();

intdenom=f.denominator();

if(temp.numerator()==0||temp.denominator()==1)

os<

else

os<

returnos;

}

问题5:

考虑到人性化的操作,实现用户不选择退出,就可以实现持续的操作,故设计了一系列的多级菜单,从而实现用户结束一个操作之后,可以选择继续本操作。

如果不继续操作,则可以选择回到上一个菜单,或者回到主菜单,或者直接退出。

但是为了实现这一系列的选择操作,可是费了一番功夫。

解决办法:

(1)首先对于是否继续的选择操作,定义的字符型变量ch,为了防止变量名重复,主菜单对应的每一个操作,在ch后都设置了不同的数字,与主菜单后的每个操作前数字一致。

利用if语句进行判断。

如果,用户选择不继续本次操作,那么就输出另一个选择菜单,选择是返回上一级的菜单还是直接退出程序,并且具备了一定的异常处理功能,如果输入错误的指令,则会显示出来,要求用户重新输入代码,为了大大简化程序,此功能利用goto语句实现。

loop1:

if(ch1=='N'||ch1=='n')

{

cout<<"1.返回主菜单;2,直接退出程序\n";

charch11;

cin>>ch11;

switch(ch11)

{

case'1':

main();

case'2':

exit(0);

default:

{cout<<"输入指令不正确,请重新输入!

\n";gotoloop1;}

}

}

(2)关于实现在函数执行过程中返回主函数,可谓大费周章了,首先通过查资料得知,在main()内部返回主函数开头,可以在语句中直接使用main();语句。

但是,在外部定义的函数中,不能使用该语句,否则将出现errorC2065:

'main':

undeclaredidentifier

errorC2373:

'main':

redefinition;differenttypemodifiers

这两个语法错误,为了解决该问题,想到了使用goto语句,但是该语句无法在函数间跳跃,故而只得作罢。

然后又想到利用返回值进行判断,但是,每次判断是,则要执行被调函数,再一次运行一次混合运算函数,或者是测试函数,显然是不可以的。

最终,查了一些资料,获得启发。

无返回值类型的函数,通过return;语句可以直接跳出该函数。

于是定义了一个全局变量judgement,当遭遇需要返回主菜单时,便将judgement进行赋值为1,随后跳出,对judgement进行判断,从而判断是否返回主菜单,如是,则配合主函数中的main()返回到主函数开头。

(3)在随后要讲到的异常处理部分,当检测到被除数为0的时候,则弹出提示消息,并且可以选择是否重新输入该数字,或者直接返回上一级菜单。

if(f2==0)

{

cout<<"被除数不能为0!

\n1.重新输入该数。

2.返回主菜单。

\n";

intk4;

cin>>k4;

if(k4==1)

{

cin>>f2;

gotoloopsmall1;

}

else{judgement=1;return;}//由此实现由外部函数直接回到主函数头部

}

if(judgement==1)main();

问题6:

混合运算的核心问题即是优先级的控制;

解决办法:

为了实现运算的优先级,则需要综合判断前后的两个运算符,首先算出优先级较高的运算符两边的数字,再对剩余的那个数字和结果进行运算,算出新的结果。

在输入的同时进行运算。

为了将运算不断向前推进,则定义了3个分数类的对象result,f1,f2.以及两个代表前后运算符的字符型变量op1,op2。

并通过对其不断赋值,如op1=op2,实现运算的推进.具体操作通过switch的嵌套实现。

过程及其繁琐,而且一旦语句出现偏差,极易出现难以发现的运行错误,即最终计算结果不正确。

一下为函数的定义:

//==========================================混合运算====================================================================

voidcomplex()

{

fractionf1,f2,result;

charop1,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";

intk4;

cin>>k4;

if(k4==1)

{

cin>>f2;

gotoloopsmall1;

}

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.返回主菜单。

";

intk4;

cin>>k4;

if(k4==1)

{

cin>>f2;

gotoloopsmall2;

}

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)end

cin>>op2;

}

switch(op1)

{

case'+':

cout<<"结果为:

"<

case'-':

cout<<"结果为:

"<

case'*':

cout<<"结果为:

"<

loopsmall3:

case'/':

if(f1==0)

{

cout<<"被除数不能为0!

\n1.重新输入该数。

2.回到主菜单。

";

intk4;

cin>>k4;

if(k4==1)

{

cin>>f1;

gotoloopsmall3;

}

else{judgement=1;return;}//1111

}cout<<"结果为:

"<

}

}

//======================================混合运算===========================================================

问题7:

异常处理,因为涉及四则运算,所以当出现被除数为0的情况,必须进行反应。

解决方案:

(1)首先是分数分母赋值为0的情况,这个在分数类的成员函数定义时就设置了反应,结果是直接退出程序。

voidfraction:

:

setden(intnewden)

{

if(newden!

=0)

d=newden;

else

{

cout<<"错误:

试图将分母设为零,不可以啊!

将直接退出程序!

\n"

<<"按任意键退出程序\n";

exit(0);

}

}

(2)然后是在运算的计算过程中,当出现被除数为0的情况,会出现提示,并且选择是否重新输入,或者返回上级菜单,重新输入通过goto语句跳转到输入语句实现。

返回上级菜单一是通过goto语句实现,若要返回到主菜单,则需要用到上面返回主函数开头的程序代码。

,其中特别注意,在混合运算函数中,需要特别设置标识loop的位置,否则经过运算符赋值,会导致计算结果错误。

(3)在随机测试的时候,取随机数的时候可能会在分母上取到0,为此,必须现在代入计算时进行检验,以防在测试过程中出现异常,而导致测试中断。

t1=rand()%10;

t2=rand()%10;

while(t1==0||t2==0)

{

t1=rand()%10;

t2=rand()%10;

}

问题8:

四则运算,菜单选择实现

都通过switch多分支语句实现,特别要注意大括号问题,嵌套一旦复杂,极易出现漏括号的现象。

因此需要注意括号的对齐,格式问题。

心得体会:

1.一个较复杂的,实现各种功能的程序,在设计的时候,可以将其不同的功能先单独书写,先行编译连接运行,调试过程中进行修改,这样比较清楚。

如果放在整个大程序中,时常会不知道问题出在哪里。

2.有时候,编译错误并不可怕,当编译没有错,但是运行结果不对时,找出BUG比较困难,必须重新从算法逻辑的角度考虑问题。

3.编写一个较大型的程序过程中,需要考虑的问题非常多,比如遇到异常输入,输入不符合规则该如何处理等等,细节问题太多了,这时,一个良好的编程习惯非常重要。

就像有时候会因为少括号而出现编译错误,括号加错地方而产生运行错误,但要是能养成括号书写对齐的习惯的话,很多这样的问题是能够避免的。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 公共行政管理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1