C++简单计算器课程设计报告.docx
《C++简单计算器课程设计报告.docx》由会员分享,可在线阅读,更多相关《C++简单计算器课程设计报告.docx(27页珍藏版)》请在冰点文库上搜索。
C++简单计算器课程设计报告
简单计算器
1根本功能描述
简单计算器包括双目运算和单目运算功能。
双目运算符包含根本的四那么运算及乘幂功能,单目运算符包含正余弦,阶乘,对数,开方,倒数等运算。
可对输入任意操作数,包括小数和整数及正数和负数进行以上的所有运算并能连续运算。
出现错误会给出相应提示,同时包含去除,退格,退出功能以及有与所有按钮相对应的菜单项。
2设计思路
如图是整个计算器的流程图,翻开计算器程序,输入数据,调用输入数据子程序。
子程序开始时m_num为零。
按下数字按钮后,判断m_num的正负号,对其进行相关处理,然后在判断是否有小数点,处理后输出结果。
回到总流程图中,输完第一个操作数后,假设按下双目运算符,那么把m_num存入num2,按下输入第二个操作数并算出结果。
假设按下的是单目运算符,那么直接对其处理得出结果。
假设按下清零,那么m_num等于0.在运算中还要判断运算是否合法,以及结果是否超出显示范围,以做出相关提示,按下清零。
算出后把结果保存至num2。
假设需用算出的结果继续运算那么回到输入完第一个操作数后,假设不需要那么判断试否需要开始新一轮的运算,不需要那么结束。
图1输入数据子函数流程图
图2简单计算器总流程图
3软件设计
3.1设计步骤
翻开,在文件中点击新建,在弹出框内选择MFCAppWizard[exe]工程,输入工程名zhoutong及其所在位置,点击确定,如图3所示。
图3新建MFCAppWizard[exe]工程
将弹出MFCAppWizard-step1对话框,选择根本对话框,点击完成,如图4所示。
图4根本对话框
这样,MFCAppWizard就建立了一个基于对话窗口的程序框架,如图5所示。
图5新建的对话框
界面设计
1、创立控件
在图5所示的ResoureView选项卡中翻开Dialog资源组,双击IDD_ZHOUTONG_DIALOG,在右边的窗口中显示出待编辑的对话框。
开始摆放控件,包括编辑框和按钮的创立。
按钮的创立以“1〞为例进行介绍,其他按钮的创立可参照此进行操作。
1〕在图5中Controls的“编辑框〞按钮上单击鼠标左键,在对话框编辑窗口上适宜的位置按下鼠标左键并拖动鼠标画出一个大小适宜的编辑框。
在编辑框上单击鼠标右键,在弹出的快捷莱单中选择属性选项,此时弹出Edit属性对话框,如图6所示,在该对话框中输入ID属性。
图6Edit属性对话框
2〕在图3中Controls的“Button〞按钮上单击鼠标左键,在对话框上的适宜的位置上按下鼠标左键并拖动鼠标画出一个大小适宜的下压式按钮。
在按钮上单击鼠标右键,在弹出的快捷菜单中选择属性选项,此时也弹出PushButton属性对话框,如图7所示,在该对话框中输入控件的ID值和标题属性。
图7PushButton属性
按照上面的操作过程编辑其他按钮和编辑框等对象的属性。
表1各按钮和编辑框等对象的属性
对象
ID
标题或说明
编辑框
IDC_xianshi
结果显示
按钮
IDC_BUTTON0
0
按钮
IDC_BUTTON1
1
按钮
IDC_BUTTON2
2
按钮
IDC_BUTTON3
3
按钮
IDC_BUTTON4
4
按钮
IDC_BUTTON5
5
按钮
IDC_BUTTON6
6
按钮
IDC_BUTTON7
7
按钮
IDC_BUTTON8
8
按钮
IDC_BUTTON9
9
按钮
IDC_change
+/-
按钮
IDC_point
.
按钮
IDC_add
+
按钮
IDC_difference
-
按钮
IDC_multiply
*
按钮
IDC_devide
/
按钮
IDC_sqrt
sqrt
按钮
IDC_daoshu
1/x
按钮
IDC_jiecheng
n!
按钮
IDC_ln
ln
按钮
IDC_sin
sin
按钮
IDC_cos
cos
按钮
IDC_pow
x^y
按钮
IDC_Onequal
=
按钮
IDC_backspace
Backspace
按钮
IDC_Onclear
Clear
完成后界面如图8所示。
图8计算器界面
2、连接变量和代码
1)给编辑框连接变量。
在编辑框上单击鼠标右键,在弹出菜单中选择ClassWizard菜单项,弹出MFCClassWizard对话框,选择MemberVariables选项卡,如图9所示。
图9MFCClassWizard对话框中的MenberVariable选项卡
在ControlIDs列表框中选择IDC_xianshi,单击AddVariables按钮,在弹出的对话框中连接变量m_num。
变量类型设定为doubel型。
如图10所示。
图10m_num属性设置
2)给“1”按钮连接代码。
在“1”按钮上单击鼠标右键,选择ClassWizard菜单项,在弹出的对话框中选择MessagesMaps选项卡,然后在ObjectIDs列表框中选择IDC_ADD_BUTTON,在Messages列表框中选择BN_CLICKED项,即选择单击按钮事件,如图11所示。
图11“1〞按钮链接代码对话框
3、菜单的设计
选择插入/资源命令,将显示插入资源对话框。
如图12所示。
选择Menu,点击新建即可。
图12插入资源对话框
ResoureView选项卡中翻开Menu资源组,双击IDR_MENU1,然后给菜单添加相应的标题,并把每个菜单对应的ID值与相应的按钮的一致。
如图13所示。
图13菜单属性对话框
在对话框的任何一个空白域单击鼠标右键,然后在弹出的快捷菜单中选择Properties命令,弹出DialogProperties对话框,如图14。
在对话框中的菜单组合框中选择IDR_MENU1。
图14对话属性对话框
最终的得到的界面如图15。
图15计算器完整界面
关键功能的实现
1〕操作数的输入
编辑框所关联的变量为m_num,程序开始时为零。
每按下一个数字键按钮,就把它累加到m_num里并刷新显示。
BOOL型变量ele来判断是否有小数点和一个整型数dint来表示小数点后的数据的位数。
当ele=TRUE时,表示有小数点,否那么那么表示无小数点。
按下小数点按钮后执行ele=TRUE。
当按下一个数字键时,首先根据ele判断是否按下小数点,假设有那么把小数点后数的位数加1,dint那么为此次键入的数所处的位数,将键入的数除以dint个10然后累加到编辑框所关联的变量m_num上,假设没有那么把m_num乘以10,然后累加到编辑框所关联的变量m_num上。
2〕单目运算符功能的实现
由于单目运算符中必须有执行运算的函数,因而头文件中要参加math.h,如m_num=sqrt(m_num).按下按钮即可实现其功能。
为实现连续运算,程序有所改动,参见〔6〕。
3〕双目运算符功能的实现
双目运算符需要两个操作数才能运算,所以在执行双目运算符按钮的函数代码中,要把m_num中的值保存到变量num2中,然后把m_num清零。
这样即可保存第一个操作数。
另外先定义了一个整形变量addt,在不同的双目运算符中给addt赋不同的值,然后在等号中用switch语句来匹配addt值来判断需要执行何种双目运算。
为实现连续运算,程序有所改动,参见〔6〕。
4〕退格键功能的实现
当按下一次退格按钮时,假设m_num为整数,只需对其中数据除以10再取整即可,假设按下一次退格按钮为小数,那么根据小数点后数据的位数dint进行操作,先对m_num执行〔dint-1〕次乘以10运算,然后取整,接着执行〔dint-1〕次除以10的运算即可。
完成后需要把dint将减小1。
5〕正负号功能的实现
在头文件中定义一个BOOL型变量ele2来判断m_num的正负。
ele2=TRUE时表示为正。
在键入操作数时需要用到ele2。
在正负号按钮的消息响应函数内容为m_num=-m_num;ele2=!
ele2。
6〕连续运算功能的实现
要连续运算必须将每次运算的结果保存下来。
对于双目运算符:
首先在等号按钮的消息处理函数中在m_num清零之前将m_num的值赋给num2.不过这样的话如果再按双目运算符那么num2的值将会被覆盖,于是在双目运算符按钮的消息处理函数中将“num2=m_num;〞改为“if(m_num!
=0)num2=m_num;〞.这样假设已经保存了结果那么不进行覆盖。
然后在每个数字按钮前加上“if(addt==0)num2=0;〞,这样如果进行完一次运算之后按下任一数字键表示不需要连续运算,那么将保存的结果删除,假设按下的是双目运算符按钮那么可以继续运算。
对于单目运算符:
每次运算完之后都会对m_num清零,因此其结果也要赋给num2,下次运算是那么会用到num2,于是第一次运算时直接将m_num的值赋给num2,对其进行运算。
以开根号为例,在消息处理函数代码中将“m_num=sqrt(m_num);〞改为“num2=m_num;m_num=sqrt(num2);num2=m_num;〞。
但是第一次运算执行完成之后m_num被清零,所以之后将m_num的值不能赋给num2,代码改为“if(m_num>=0)m_num=sqrt(num2);num2=m_num;〞。
其他单目运算符同理。
为实现连续运算是不需要按下等号即可实现,又在所有的运算符按钮的消息处理函数代码前加上了“if(addt!
=0)Onequal();〞。
既假设之前有按下双目运算符和两个操作数那么连续运算再按下任一运算符时会自动调用等号的处理函数将上次的运算完成并保存结果方便下一次的运算。
4结论与心得体会
经过多番测试,得出结论为设计的计算器能够完成功能描述内容中的全部功能。
经过2个星期的VC++课程设计,我在老师和同学的共同帮助下,顺利完成该课程设计,收获很大。
本学期我们开设了?
面向对象程序设计与VC++实践?
课MFC局部皆为需要实践内容,正所谓“纸上谈兵终觉浅,觉知此事要躬行。
〞所以在本学期课程设计是很及时、很必要的。
这样不仅能加深我们对MFC程序设计的掌握,而且还及时、真正的做到了学以致用。
主要是以下几点。
根本功要过硬。
不能马虎经常犯犯小错误。
提高自己找错纠错能力,通常错误总是那几种,多练习就熟练了。
要善于查找资料提高自己的资料查询能力,要善于利用网络来获得知识,获得帮助。
开始着手程序设计时,有些功能感觉无从下手,都不知道要干什么。
这些问题只要找到相关的资料就会得到提示从而理解所要解决问题的大致方向。
有了明确的目的,就可以发挥自己的头脑来完成它了。
要善于思考。
程序中有些实现难点和最初完成程序时免不了的许多缺乏就需要自己根据代码认真思考来解决。
只有这样才能纠正程序的缺乏并使其更加人性化。
这次课程设计让我学到了很多,不仅是稳固了先前学的MFC程序设计知识,而且也培养了我的动手能力,更令我的创造性思维得到拓展。
希望今后类似这样课程设计、类似这样的锻炼时机能更多些!
5参考文献
[1]揣锦华.面向对象程序设计与VC++实践.西安电子科技大学出版社,2005
[2]张建宏,汤练兵,马德骏.计算机程序设计根底-C语言程序设计.科学出版社,2006
[3]陈清华.VisualC++课程设计案例精选与编程指导.东南大学出版社,2004
6思考题
1、程序中如何实现小数的显示与运算?
答:
在头文件中定义一个BOOL型变量ele来判断是否有小数点和一个整型数dint来表示小数点后的数据的位数。
当ele=TRUE时,表示有小数点,否那么那么表示无小数点。
按下小数点按钮后执行ele=TRUE。
首先根据ele判断是否按下小数点,假设有那么把小数点后数的位数加1,dint那么为此次键入的数所处的位数,将键入的数除以dint个10然后累加到编辑框所关联的变量m_num上。
2、描述等号对应的消息处理函数中需要处理的问题及相应的实现代码?
答:
在双目运算符按钮函数代码中将整形变量addt赋值,然后在等号中用switch语句来匹配addt值来判断需要执行何种双目运算。
并将结果保存以进行下次运算时使用,玩筹划那个一些变量的清零。
实现代码如下:
switch(addt)//数据判断
{
case0:
//为实现连续按下两次等号后能清零
UpdateData(FALSE);//数据刷新
break;
case1:
m_num=num2+m_num;//两数相加
UpdateData(FALSE);//数据刷新
break;
case2:
m_num=num2-m_num;//两数相减
UpdateData(FALSE);//数据刷新
break;
case3:
m_num=num2*m_num;//两数相乘
UpdateData(FALSE);//数据刷新
break;
case4:
if(m_num==0)//在除法中,判断除数是否为0
GetDlgItem(IDC_xianshi)->SetWindowText("错误,0不能作除数");
else{m_num=num2/m_num;UpdateData(FALSE);}
break;
case5:
m_num=pow(num2,m_num);//取模
UpdateData(FALSE);//数据刷新
break;
}
if(m_num>=1.7E308||m_num<-1.7E308)
GetDlgItem(IDC_xianshi)->SetWindowText("结果过大,无法显示");
num2=m_num;
m_num=0;
num1=0;
dint=0;
ele=FALSE;
addt=0;
ele2=TRUE;
7附录
调试报告
1、编译时提示错误:
“C:
\DocumentsandSettings\周同\桌面\zhoutong\zhoutongDlg.cpp(230):
errorC2018:
unknowncharacter'0xa3'
C:
\DocumentsandSettings\周同\桌面\zhoutong\zhoutongDlg.cpp(230):
errorC2018:
unknowncharacter'0xbb'
C:
\DocumentsandSettings\周同\桌面\zhoutong\zhoutongDlg.cpp(231):
errorC2143:
syntaxerror:
missing';'before'if'〞
原因为分号是在中文输入法状态下输入,将其改为英文输入状态下了分号即可。
2、重做时调用其他工程中的对话框资源后编译链接运行后还是本来有的那个对话框,后来将原先的对话框资源删除并将调用的对话框的ID改为原先的对话框的ID,再次编译链接运行之后没有反响了,经过屡次摸索发现调用过来的对话框是关联了菜单了,而新建的工程里没有菜单,因此将调用的对话框取消与菜单的关联,再次再次编译链接运行之后一切正常。
3、用GetDlgItem(IDC_NAME_EDIT)->SetWindowText("");来提示操作错误时,总是没有任何效果,经老师帮助得以解决。
因为UpdateData(FALSE)是将变量传到前台显示,SetWindowText就是设置前台显示的新内容。
所以在SetWindowText后如果还有UpdateData(FALSE)那么其效果会被后者覆盖,因此程序中SetWindowText之后不用UpdateData(FALSE)即可。
4、当操作数超过10位数时,用backspace会出现错误结果,一番研究研究发现用int(m_num)取整有问题,int只有4个字节,当超过其范围时就会出错。
因此将取整的方法改为先用fmod取其除以1的余数得到其小数位,然后用m_num减去其小数位即可。
测试结果
“”,“-〞,“”,“+〞,“”,“=〞,并在菜单中同样输入这组操作,均得到结果如图16。
图16结果图1
结果正确,证明可以实现双目运算符的连续运算,菜单功能正常。
2.输入“901”,“+/-〞,“backspace〞,“+〞,“120”,“sin〞,结果如图17.
图17结果图2
因为π取的是,因此与有小小偏差,认为结果正确。
证明可以实现单目运算符的连续运算与backspace回格功能。
3.输入“0”,“ln〞,结果如图18.
结果图18
证明错误提示功能实现正常。
关键源代码
1、变量的定义:
BOOLele2;//ele定义为布尔值,判断当前值是否是正数还是负数
intaddt;
inti;
intdint;//dent判断小数后的位数
BOOLele;//ele2定义为布尔值,判断是否有小数点
doublenum2;
doublenum1;
2、程序运行时初始化和头文件:
在zhoutongDlg.cpp的OnInitDialog()里调用Onclear();
zhoutongDlg.cpp里加上头文件#include"math.h"
3、数字键1的程序:
〔数字键2到9类似〕
if(addt==0)num2=0;
if(ele2==TRUE)
m_num=m_num*10+1;//单击数字键1后把数据传送到输出框中
elsem_num=m_num*10-1;
if(ele==TRUE)//当前是否有小数点,如果有
{
num1=1;
dint=dint++;
for(i=0;i{
num1=num1/10;//1/10,得到的小数放入输出框中
}
if(ele2==TRUE)//当前值是否是正数还是负数,如果是正数
m_num=(m_num-1)/10+num1;//前面不加负号
else
m_num=(m_num+1)/10-num1;//否那么前面加负号
}
UpdateData(FALSE);//数据刷新
4、数字键0的程序:
if(addt==0)num2=0;
m_num=m_num*10;//点击数字键0后把数据传送到输出框
if(ele==TRUE)//判断当前是否有小数点
{
dint=dint++;//判断位数
m_num=m_num/10;//把数除以10后以小数传送到输出框
5、加法键+的程序:
〔-,*,/,x,x^y的代码类似〕
if(addt!
=0)Onequal();
if(num2==0)num2=m_num;//把第二个值赋于输出框的成员变量
m_num=0;//输出框的成员变量清0
ele=FALSE;//当前小数无
ele2=TURE;//当前符号为正
dint=0;//小数位数无
addt=1;
6、Sqrt键的程序:
if(addt!
=0)Onequal();
if(m_num!
=0)num2=m_num;
if(m_num>=0)
{
m_num=sqrt(num2);//对数进行开根号
UpdateData(FALSE);//数据刷新
num2=m_num;
}
elseGetDlgItem(IDC_xianshi)->SetWindowText("错误,负数不能开根号");
m_num=0;
num1=0;
dint=0;
ele=FALSE;
ele2=TRUE;
7、n!
键的程序:
if(addt!
=0)Onequal();
if(m_num!
=0)num2=m_num;
if(fmod(num2,1)==0)
{
m_num=1;
for(i=1;i<=num2;i++)m_num*=i;//对数进行求阶乘
UpdateData(FALSE);//数据刷新
num2=m_num;
if(m_num>=1.7E308||m_num<-1.7E308)
GetDlgItem(IDC_xianshi)->SetWindowText("结果过大,无法显示");
}
elseGetDlgItem(IDC_xianshi)->SetWindowText("不是整数无法进行阶乘运算");
m_num=0;
num1=0;
dint=0;
ele=FALSE;
ele2=TRUE;
8、1/x键的程序:
if(addt!
=0)Onequal();
if(m_num!
=0)num2=m_num;
if(num2!
=0)
{
m_num=1.0/num2;//对数进行求倒数
UpdateData(FALSE);//数据刷新
num2=m_num;
if(m_num>=1.7E308||m_num<-1.7E308)
GetDlgItem(IDC_xianshi)->SetWindowText("结果过大,无法显示");
}
elseGetDlgItem(IDC_xianshi)->SetWindowText("错误,0不能求倒数");
m_num=0;
num1=0;
dint=0;
ele=FALSE;
ele2=TRUE;
9、sin键的程序:
(cos的代码类似)
if(addt!
=0)Onequal();
if(m_num!
=0)num2=m_num;
m_num=sin(num2*3.1415926/180);//对数进行正弦
UpdateData(FALSE);//数据刷新
num2=m_num;
m_num=0;
num1=0;
dint=0;
ele=FALSE;
ele2=TRUE;
10、ln键的程序:
if(addt!
=0)Onequal();
if(m_num!
=0)num2=m_num;
if(m_num>0)
{
m_num=log(num2);//对数进行求ln
UpdateData(FALSE);//数据刷新
num2=m_num;
}
elseGetDlgItem(IDC_xianshi)->SetWindowText("错误,操作数需大于0");
m_num=0;
num1=0;
dint=0;
ele=FALSE;
ele2=TRUE;
11、=键的程序:
switch(addt)//数据判断
{
case0:
//为实现连续按下两次等号后能清零
UpdateData(FALSE);//数据刷新
break;
case1:
m_num=num2+m_num;//两数相加
UpdateData(FALSE);//数据刷新
break;
case2:
m_num=num2-m_num;//两数相减
UpdateData(FALSE);//数据刷新
break;
case3:
m_num=num2*m_num;//两数相乘
UpdateData(FALSE);//数据刷新
break;
case4:
if(m_num==0)//在除法中,判断除数是否为0
GetDlgItem(IDC_xianshi)->SetWindowText("错误,0不能作除数");
else{m_nu