MFC简单计算器设计正文_第1页
MFC简单计算器设计正文_第2页
MFC简单计算器设计正文_第3页
MFC简单计算器设计正文_第4页
MFC简单计算器设计正文_第5页
已阅读5页,还剩31页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、实用计算器程序1.基本功能描述计算器是人们日常生活中非常实用的计算工具。预期设计目标与实际计算器为标准,Windows 10系统提供的计算器为范例进行设计。实用计算器要实现单目运算和双目运算。单目运算主要包括阶乘、正弦、余弦;双目运算主要包括加、减、乘、除、乘幂等。计算器要能够对输入的各种数据进行处理,包括小数、整数、负数等数据进行操作。实际过程中要能够对不同的数据灵活判断执行。同时要能够对不满足运算符的操作数,提示出错信息以方便用户进行处理。用户的修改包括清屏和退格。程序设计的重点和难点在于:第一,能够对于不同的操作数和操作符进行连续运算,运算过程中要有优先级的判断,根据优先级执行不同的运算

2、顺序;第二,能够用一个编辑框实现运算表达式的显示和结果的输出。编程环境采用Visual Studio 2017提供的MFC建立对话框应用程序,设计界面要简单大方,并提供程序所有功能的接口。2.设计思路表1 操作符优先级设计优先级操作符1阶乘、正弦、余弦2乘幂3乘、除4加、减对对话框编辑框关联一个变量从中读取数据,按下数字键时对数据数组num进行更新,其中num0表示的是当前已经存储变量的个数。由于算法设计为四层优先级,且单目运算的优先级最高。当按下相应单目运算符,首先将当前数据数组的最后一个存储(防止按下Backspace退格发生错误),并将此位数据执行运算后重新赋值。但按下双目运算符相应按键

3、后,将计数num0+,同时将运算符的类型和位置记录。当按下等于之前,这样就将一个单目双目混合的运算表达式转化为双目运算。如果没有按下等号键,则继续执行循环。在按下等号按钮之后,按照先乘幂、再乘除、后加减的运算顺序执行运算,将最后结果保存并显示。(在实际的计算器中,执行完运算之后,按下运算符的操作键,最终结果将按照左操作数的形式出现,故需要保存变量。)如果用户没有结束程序,在运行初始化程序,进行下一次运算,否则直接退出。图1 程序流程图3.软件设计3.1 设计步骤 1)创建基于对话框的程序利用AppWizard建立应用程序框架,创建一个基于对话框的MFC工程,命名为“fengwanjincalc

4、ulator”,如图2所示。在图3显示的应用程序类型中选择基于对话框。创建成功后,系统自动生成相应程序文件。图2 创建MFC工程图图3 应用程序类型选择图2)定义成员变量添加相应变量和标志位,以方便程序的编写,主要变量如表2所示:表2 成员变量表变量名变量类型变量作用mystrCString编辑框关联变量m_editFontCFont设置编辑框字体numfloat存储操作数flagdianbool点号标志位flagdengyubool等号标志位flagerrorbool错误标志位Jiajianint存储加减运算符的位置4) 添加事件处理程序MFC应用程序是通过消息响应来进行各项操作的,必须在对

5、话类中加入消息处理函数来处理这些事件。当点击相应控件,在进入WinMain函数之前,每个可以响应消息的MFC类都生成了一个消息映射表,程序运行时通过查询该表判断是否需要响应某条消息。在相应控件单击右键,弹出图4,选择添加事件处理程序,在图5的事件处理程序向导中选择fengwanjincalculatorDlg类,消息类型选择为BN_CLICKED,即左键单击。图4 添加事件处理程序图5 选择添加事件处理程序类型在完成上述操作后 MFC使用ClassWizard帮助实现消息映射,它在源码中添加一些消息映射的内容,并声明和实现消息处理函数。首先,在类的定义(头文件)里,它增加了消息处理函数声明,并

6、添加一行声明消息映射的宏DECLARE_MESSAGE_MAP。在类的实现(实现文件)里,实现消息处理函数,并使用IMPLEMENT_MESSAGE_MAP宏实现消息映射。BEGIN_MESSAGE_MAP*END_MESSAGE_MAP3.2 界面设计图5 向对话框添加控件在项目的资源视图中找到位于Dialog下的对话框,如图4所示。添加相应控件,完成用户界面设计。图6 用户界面设计其中编辑框行为下Multiline属性设置为True,作为多行编辑框。第一行显示算式,第二行结果。整体上将控件分为四组,数值控件区NUM,加减乘除一般运算控件区NORMAL,阶乘、乘幂、正余弦科学运算控件区SCI

7、ENCE以及清零退格控件。设计完成后的界面如图7所示。图7 用户界面设计的界面中只有编辑框关联Cstring类型变量mystr。其余控件关联相应的消息处理函数。3.3 关键功能的实现程序主要分为数值、单目运算、双目运算、清除等。1) 数值控件消息处理函数void CfengwanjincalculatorDlg:OnBnClickedButton1()shuzihanshu(L'1', 1);考虑到09数字的处理函数有很大的相似处,所以都采用调用shuzhihanshu函数的方法执行。shuzhihanshu包含两个参数,分别是数值对应字符和相应数值。其具体实现如下:void

8、CfengwanjincalculatorDlg:shuzihanshu(char shuzi, int shuzhi)/09对应函数UpdateData(TRUE);if (flagdengyu)OnBnClickedButtonClear();flaglast = 0;mystr += shuzi;data = shuzhi;changevalue();UpdateData(FALSE);首先,判断再点击数值控件之前是否按下等号键,如果按下执行OnBnClickedButtonClear(),即执行清除函数,然后将单击的数值显示在编辑框中。如果之前没有单击等号,则直接将数值添加到显示字符串

9、的最后,通过UpdateData(FALSE)更新编辑框控件。同时需要将数值传递给data,通过changevalue()函数改变数值数组中的数值。2)双目运算消息处理函数void CfengwanjincalculatorDlg:OnBnClickedButtonJia()/加sincos();if (flaglast = 0)|(flaglast = jiecheng)shuangmusuanfu(L'+', jia);flaglast = jia;jiajian0+;jiajianjiajian0 = 1;双目运算首先设置相应标志和参数的改变,其主要的函数体部分由shua

10、ngmusuanfu函数概括,其中jia参量为用枚举定义的一个常量。枚举定义如下:enum suit jia = 1 , jian , cheng , chu , jiecheng , zhishu , Sin , Cos ;shuangmusuanfu中函数实现部分:函数体中首先对是否按下等号是否有表达式错误进行判断,如果相应标志为1,则转到相应处理函数,否则将算符存储,数值计数器num0加一。3)清除函数void CfengwanjincalculatorDlg:OnBnClickedButtonClear()UpdateData(TRUE);mystr = L""fl

11、agdian = 0;beishu = 1;flagerror = 0;data = 0;flagdengyu = 0;for (int i = 0; i < 10; i+)jiajiani = 0;chengchui = 0;mizhii = 0;numi = 0;nextdatai = 0;num0 = 1;flaglast = 0;UpdateData(FALSE);清除函数中主要讲各个参量重新初始化,同时通过UpdateData(FALSE)更新编辑框控件。4. 结论与心得体会1、Windows编程中可能会遇到可能会遇到各种编译问题,例如编译环境的设置,具体函数的调用。同时Win

12、dows为程序员提供了大量的库函数,在具体实践的过程中,要充分利用书籍和网络查阅相关函数和环境设置,减轻编程负担。2、考虑到编程的难度,首先编写了未设置优先级的表达式运算,后又通过在原先程序的基础上,编写了设置优先级的程序。由于两种方式在算法设计上有很大不同,导致了程序改进的困难。3、由于在编程思想方面并没有参照网上的先例,也没有采取堆栈的方式进行优先级的运算,在具体编程的过程中遇到了很多细节问题。所以在日后的编程中要注意,算法与数据结构的结合。4、相较于传统的C+编程,MFC的编程不仅要考虑算法和数据结构的问题,还需要考虑环境、用户界面的美观便捷等问题,编程的难度更大,出现的问题也更多,在编

13、程的过程中渐渐提高了自己的耐性和对于新事物的应用能力。5、从本次编程的结果来看,此次编程需要提高的方面还很多,人机交互界面的设计、程序算法的统一性、可读性都有待提高。在程序的设计过程中主要参考了Windows 10参做系统自带的计算器,交互界面如图8所示:图8 Windows 10计算器仅从界面看,差距还很大。但是任何一个程序都不可能是完美的,这款计算器在调试的过程中也发现了一些bug,所以在日后更加重要的学习和工作中的编程过程中,要注意程序的调试和检查,完善任何一个优秀程序都是需要细致耐心的打磨。5. 思考题1、程序如何实现小数的显示和运算?首先,数值数组采用float类型,可以实现整形和浮

14、点型的统一运算。在读取数值的过程中要加入小数点的判断,如果出现了小数点,则在之后读取的每一个数值需要将相应的倍数每次除以10乘以读出的数值与原数值相加得到。例如changevalue函数:void CfengwanjincalculatorDlg:changevalue()if (!flagdian)num(int)num0 = data + num(int)num0 * 10;elsebeishu /= 10;num(int)num0 = num(int)num0 + data * beishu;对于例如阶乘等只能对于整形进行运算的运算符或函数,首先对数值取证判断其是否与原数据相等,如果相等

15、则可以进行相应运算。如果不同,则通过AfxMessageBox函数弹出错误提示,错误窗口如图9所示:图9 错误提示窗口2、描述等号对应的消息处理函数中需要问题及相应实现代码?点击等号控件,则首先要进行表达式是否正确的判断(本次程序编写过程中,运算符操作的合法性检查放在了每个运算符的函数中,故在等号的消息处理函数中不需要再添加),将结果计算得出并显示在窗口上,同时设置相应的标志。具体代码如下:void CfengwanjincalculatorDlg:OnBnClickedButtonDeng()/等于sincos();CString temp;calculator();if (!flagerr

16、or)temp.Format(_T("%g"), num1);mystr += L"rn"mystr += temp;flagdian = 0;beishu = 1;flagerror = 0;flagdengyu = 1;UpdateData(FALSE);在实现过程中,首先通过calculator()执行相应运算得到结果,发生没有错误则将结果显示在编辑框中。同时设置标志位,标志等号消息处理函数已经运算完。6、附录6.1 调试报告程序编译运行过程中主要遇到了类型转换问题、函数调用或执行问题、结果错误问题等。1、类型转换问题此类问题错误提示比较明确,更改

17、也比较容易,只需要双击错误提示,转到相应的出错代码,进行相应处理即可。例如,num数组设置为float类型,而为了减少变量的个数,采用num数组的第一位作为数组中数值个数的计数器。故采用numnum0表示最后一位数值,程序报错,提示只能为整数下标。改为强制类型转换即可num(int)num0。2、函数调用或执行问题此类问题一般在编译过程中并不报错或者不能给出有效的错误提示,导致发现的困难性。例如,在CfengwanjincalculatorDlg类自声明了一个函数,而在相应的.cpp文件中忘记相应函数实现的编写,编译运行过程中仅提示找不到相应的.exe文件。通过pause函数等暂停函数到某一点

18、,找到错误的区间解决问题。2、结果错误问题此类问题在本次编程过程中遇到的情况较多,采用的自己模拟程序执行流程发现问题,如果不能通过这种方式发现,则通过设置断点,单步执行观察变量在每一步中的变化,并于自己的设想相比较发现问题。6.2 测试结果1、键入表达式125+6*5-8!+73点击等号得到表达式的结果,与实际相一致,如图10所示。图10 键入数值并执行运算2、点击加号后可以继续执行运算。图11 点击加号继续运算3、按下数值9,清屏屏显示数值9图12 按下数值94、清屏图13 清屏5、错误提示图14 错误提示6.3关键源代码1、fengwanjincalculatorDlg.h文件中自定义变量

19、和函数的相应声明:public:int jiajian10;/第一位为加减算符个数,后面几位的绝对值为位置,+为正,-为负int chengchu10;/第一位为乘除算符个数,后面几位的绝对值为位置,+为正,-为负int mizhi10;/第一位为乘幂算符个数,后面几位的绝对值为位置,+为正,-为负float num10;/操作数数值数组int flaglast;/判断表达式最后一位为算符或者数值 0为数值,18为相应算符float nextdata10;CString mystr;/编辑框字符串CFont m_editFont;/编辑框字体bool flagdian;/0为没加点1为加了点f

20、loat beishu;/倍数bool flagerror;/0未发生错误1发生错误int data;/按键数值bool flagdengyu;/是否按下=void calculator();/计算函数void changevalue();/改变操作数void shuangmusuanfu(char,int);/双目算符对应函数void shuzihanshu(char, int);/数字对应函数void sincos();afx_msg void OnBnClickedButton1();afx_msg void OnBnClickedButton2();afx_msg void OnBnC

21、lickedButton3();afx_msg void OnBnClickedButton4();afx_msg void OnBnClickedButton5();afx_msg void OnBnClickedButton6();afx_msg void OnBnClickedButton7();afx_msg void OnBnClickedButton8();afx_msg void OnBnClickedButton9();afx_msg void OnBnClickedButtonDian();afx_msg void OnBnClickedButton0();afx_msg v

22、oid OnBnClickedButtonClear();afx_msg void OnBnClickedButtonBackspace();afx_msg void OnBnClickedButtonJia();afx_msg void OnBnClickedButtonDeng();afx_msg void OnBnClickedButtonJian();afx_msg void OnBnClickedButtonCheng();afx_msg void OnBnClickedButtonChu();afx_msg void OnBnClickedButtonZhishu();afx_ms

23、g void OnBnClickedButtonJiecheng();afx_msg void OnBnClickedButtonSin();afx_msg void OnBnClickedButtonCos();2、在fengwanjincalculatorDlg.cpp文件中声明的枚举类型enum suit jia = 1 , jian , cheng , chu , jiecheng , zhishu , Sin , Cos ;3、CfengwanjincalculatorDlg构造函数中的初始化CfengwanjincalculatorDlg:Cfengwanjincalculator

24、Dlg(CWnd* pParent /*=NULL*/): CDialog(IDD_FENGWANJINCALCULATOR_DIALOG, pParent), mystr(_T("")m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);/ 自添加flagdian = 0;beishu = 1;flagerror = 0;data = 0;flagdengyu = 0;for (int i = 0; i < 10; i+)jiajiani = 0;chengchui = 0;mizhii = 0;numi = 0;nex

25、tdatai = 0;num0 = 1;flaglast=0;4、CfengwanjincalculatorDlg:OnInitDialog()设置编辑框字体m_editFont.CreatePointFont(180, "宋体");CEdit *m_Edit = (CEdit *)GetDlgItem(IDC_EDIT);m_Edit->SetFont(&m_editFont); / 设置新字体5、清屏函数void CfengwanjincalculatorDlg:OnBnClickedButtonClear()/ TODO: 在此添加控件通知处理程序代码U

26、pdateData(TRUE);mystr = L""flagdian = 0;beishu = 1;flagerror = 0;data = 0;flagdengyu = 0;for (int i = 0; i < 10; i+)jiajiani = 0;chengchui = 0;mizhii = 0;numi = 0;nextdatai = 0;num0 = 1;flaglast = 0;UpdateData(FALSE);5、退格函数void CfengwanjincalculatorDlg:OnBnClickedButtonBackspace()/ TODO

27、: 在此添加控件通知处理程序代码UpdateData(TRUE);/移除最右边一个字符 if (!mystr.IsEmpty()char temp;temp = mystrmystr.GetLength() - 1;if (temp >= 48 && temp <= 57)if (!flagdian)num(int)num0 = (num(int)num0 - (temp - 48) / 10;elsenum(int)num0 = num(int)num0 - (temp - 48)*beishu;beishu *= 10;mystr = mystr.Left(my

28、str.GetLength() - 1);else if (temp = '.')flagdian = 0;mystr = mystr.Left(mystr.GetLength() - 1);elsenum0-;switch (temp)case 43:case 45:jiajianjiajian0 = 0;jiajian0-;mystr = mystr.Left(mystr.GetLength() - 1);break;case 42:case 47:chengchuchengchu0 = 0;chengchu0-;mystr = mystr.Left(mystr.GetLe

29、ngth() - 1);break;case 33:num0+;num(int)num0 = nextdata2 * (int)nextdata0;nextdata2 * (int)nextdata0 - 1 = 0;nextdata0-;mystr = mystr.Left(mystr.GetLength() - 1);break;case 94:mizhimizhi0 = 0;mizhi0-;mystr = mystr.Left(mystr.GetLength() - 1);break;case 110:num0+;num(int)num0 = nextdata2 * (int)nextd

30、ata0;nextdata2 * (int)nextdata0 - 1 = 0;nextdata0-;mystr = mystr.Left(mystr.GetLength() - 3);break;case 115:num0+;num(int)num0 = nextdata2 * (int)nextdata0;nextdata2 * (int)nextdata0 - 1 = 0;nextdata0-;mystr = mystr.Left(mystr.GetLength() - 3);break;default:break;flaglast = 0;UpdateData(FALSE);6、改变数

31、值数组void CfengwanjincalculatorDlg:changevalue()if (!flagdian)num(int)num0 = data + num(int)num0 * 10;elsebeishu /= 10;num(int)num0 = num(int)num0 + data * beishu;7、表达式求值函数void CfengwanjincalculatorDlg:calculator()/计算for (; mizhi0 > 0; mizhi0-)nummizhimizhi0 = pow(nummizhimizhi0, nummizhimizhi0+1);

32、for (int i = mizhimizhi0+1; i < num0; i+)numi = numi + 1;num0-;for (int i = 1; i <= chengchu0; i+)if (abs(chengchui) > mizhimizhi0)if (chengchui > 0)chengchui -= 1;elsechengchui += 1;for (; chengchu0 > 0; chengchu0-)if (chengchuchengchu0 > 0)numchengchuchengchu0 *= numchengchucheng

33、chu0 + 1;elseif (num-chengchuchengchu0 + 1 = 0)AfxMessageBox(_T("除数不能为0!");flagerror = 1;OnBnClickedButtonClear();break;elsenum-chengchuchengchu0 /= num-chengchuchengchu0 + 1;for (int i = abs(chengchuchengchu0) + 1; i < num0; i+)numi = numi + 1;num0-;float sum = num1;for (int i = 2; i &

34、lt;= num0; i+)sum += jiajiani-1 * numi;for (int i = 0; i < 10; i+)numi = 0;num1 = sum;num0 = 1;8、双目算符对应函数void CfengwanjincalculatorDlg:shuangmusuanfu(char zifu,int shuzhi)/ 双目算符对应函数UpdateData(TRUE);if (flagdengyu = 1)mystr = L""flagdian = 0;beishu = 1;flagdengyu = 0;for (int i = 0; i &l

35、t; 10; i+)jiajiani = 0;chengchui = 0;mizhii = 0;flaglast = 0;if (!flagerror)mystr.Format(_T("%g"), num1);elsefor (int i = 0; i < 10; i+)numi = 0;flagdengyu = 0;num0+;/数值个数+if (!flagerror)mystr += zifu;flagdian = 0;beishu = 1;flagerror = 0;UpdateData(FALSE);9、09对应函数void Cfengwanjincalcul

36、atorDlg:shuzihanshu(char shuzi, int shuzhi)/09对应函数UpdateData(TRUE);if (flagdengyu)OnBnClickedButtonClear();flaglast = 0;mystr += shuzi;data = shuzhi;changevalue();UpdateData(FALSE);10、各控件消息响应函数void CfengwanjincalculatorDlg:OnBnClickedButton1()/ TODO: 在此添加控件通知处理程序代码shuzihanshu(L'1', 1);void C

37、fengwanjincalculatorDlg:OnBnClickedButton2()/ TODO: 在此添加控件通知处理程序代码shuzihanshu(L'2', 2);void CfengwanjincalculatorDlg:OnBnClickedButton3()/ TODO: 在此添加控件通知处理程序代码shuzihanshu(L'3', 3);void CfengwanjincalculatorDlg:OnBnClickedButton4()/ TODO: 在此添加控件通知处理程序代码shuzihanshu(L'4', 4);voi

38、d CfengwanjincalculatorDlg:OnBnClickedButton5()/ TODO: 在此添加控件通知处理程序代码shuzihanshu(L'5', 5);void CfengwanjincalculatorDlg:OnBnClickedButton6()/ TODO: 在此添加控件通知处理程序代码shuzihanshu(L'6', 6);void CfengwanjincalculatorDlg:OnBnClickedButton7()/ TODO: 在此添加控件通知处理程序代码shuzihanshu(L'7', 7);

39、void CfengwanjincalculatorDlg:OnBnClickedButton8()/ TODO: 在此添加控件通知处理程序代码shuzihanshu(L'8', 8);void CfengwanjincalculatorDlg:OnBnClickedButton9()/ TODO: 在此添加控件通知处理程序代码shuzihanshu(L'9', 9);void CfengwanjincalculatorDlg:OnBnClickedButton0()/ TODO: 在此添加控件通知处理程序代码shuzihanshu(L'0',

40、0);void CfengwanjincalculatorDlg:OnBnClickedButtonDian()/ TODO: 在此添加控件通知处理程序代码UpdateData(TRUE);if (flagdengyu)OnBnClickedButtonClear();elseif(flagdian=0)mystr += L"."flagdian = 1;flaglast = 0;UpdateData(FALSE);void CfengwanjincalculatorDlg:sincos()if (nextdata2 * (int)nextdata0 - 1 = Sin)n

41、extdata2 * (int)nextdata0 = num(int)num0;num(int)num0 = sin(num(int)num0);nextdata2 * (int)nextdata0 - 1 = -Sin;if (nextdata2 * (int)nextdata0 - 1 = Cos)nextdata2 * (int)nextdata0 = num(int)num0;num(int)num0 = cos(num(int)num0);nextdata2 * (int)nextdata0 - 1 = -Cos;void CfengwanjincalculatorDlg:OnBn

42、ClickedButtonJia()/加/ TODO: 在此添加控件通知处理程序代码sincos();if (flaglast = 0)|(flaglast = jiecheng)shuangmusuanfu(L'+', jia);flaglast = jia;jiajian0+;jiajianjiajian0 = 1;void CfengwanjincalculatorDlg:OnBnClickedButtonJian()/减/ TODO: 在此添加控件通知处理程序代码sincos();if (flaglast = 0) | (flaglast = jiecheng)shua

43、ngmusuanfu(L'-', jian);flaglast = jian;jiajian0+;jiajianjiajian0 = -1;void CfengwanjincalculatorDlg:OnBnClickedButtonCheng()/乘/ TODO: 在此添加控件通知处理程序代码sincos();if (flaglast = 0) | (flaglast = jiecheng)shuangmusuanfu(L'*', cheng);flaglast = cheng;chengchu0+;chengchuchengchu0 = (int)num0-

44、1;void CfengwanjincalculatorDlg:OnBnClickedButtonChu()/除/ TODO: 在此添加控件通知处理程序代码sincos();if (flaglast = 0) | (flaglast = jiecheng)shuangmusuanfu(L'/', chu);flaglast = chu;chengchu0+;chengchuchengchu0 = -(int)num0-1);void CfengwanjincalculatorDlg:OnBnClickedButtonZhishu()/指数/ TODO: 在此添加控件通知处理程序代码sincos();if (flaglast = 0) | (flaglast = jiecheng)shuangmusuanfu(L'', zhishu);flaglast = zhishu;mizhi0+;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论