当前位置:首页 >> 计算机软件及应用 >>

迷你计算器


*******************

实践教学
*******************

兰州理工大学
计算机与通信学院 2013 年秋季学期

面向对象

课程设计

题 目: 专业班级: 姓 名: 学 号: 指导教师: 成 绩:

迷你计算器


问题描述: 编写一个程序来实现算术计算器。 设计背景:



随着科学技术的发展,计算器成为 IT 领域必不可少的一部分。此次面向对 象课程设计,要求设计一款“迷你计算器”,以便实现简单的加、减、乘、除等简 单的四则运算以及简单的函数运算。在设计的同时,复习所学过的知识,通过查 询资料来完成设计,并拓展知识面。 实现方式: Visual C++ 6.0 下使用 MFC 编程实现。





摘 要............................................................................................................................ 1 第一章 软件总体设计.................................................................................................. 2 1.系统功能模块图................................................................................................ 2 2.各类间关系........................................................................................................ 2 第二章 详细设计.......................................................................................................... 4 1.总体设计............................................................................................................ 4 2.部分函数调用关系............................................................................................. 5 3.相关函数和变量说明........................................................................................ 6 4.详细设计............................................................................................................ 7 1)、数值输入和显示 .................................................................................. 10 2)、进制转换 .............................................................................................. 10 3)、双字单字和字节 .................................................................................. 10 4)、记忆系统 .............................................................................................. 10 5)、退格 ...................................................................................................... 10 6)、Inv ......................................................................................................... 10 7)、键盘快捷键 .......................................................................................... 11 8)、程序核心 .............................................................................................. 13 第三章 系统测试........................................................................................................ 16 1.测试方法.......................................................................................................... 16 2.测试用例.......................................................................................................... 16 3.测试结果.......................................................................................................... 16 第四章 软件使用说明书............................................................................................ 17 1.系统运行环境.................................................................................................. 17 2.程序主要功能.................................................................................................. 17 3.使用说明.......................................................................................................... 17 总 结.......................................................................................................................... 18 参考文献...................................................................................................................... 19 致谢.............................................................................................................................. 20 附件:程序原代码...................................................................................................... 21 1.calcDlg.cpp ....................................................................................................... 21 2.calc.cpp ............................................................................................................. 51 3.其他代码及头文件.......................................................................................... 53





迷你计算器是一款仿 Windows 计算器界面的简单计算器。其开发主要包括 简单的加、减、乘、除四则运算以及简单的函数运算。简单计算器包括双目运算 和单目运算功能。 双目运算符包含基本的四则运算及乘幂功能,单目运算符包含 正余弦,阶乘,对数,开方,倒数等运算。可对输入任意操作数,包括小数和整 数及正数和负数进行以上的所有运算并能连续运算。出现错误会给出相应提示, 同时包含清除,退格,退出功能以及有与所有按钮相对应的菜单项。 用面向对象编程的思想与方法, 实现一个简单计算器的分析与设计阶段的开 发工作,开发工具使用 Visual C++6。本系统为简单计算器程序开发,实现基本 的算术运算以及科学计算, 具备计算历史的查询功能,并能检查算术表达式中的 错误,分别以二进制、十进制等数制的计算。 本软件的开发采用面向对象的设计思想。 系统的介绍了迷你计算器的开发过 程及面向对象思想的具体实现。

关键词: Visual C++ 6.0;MFC;迷你计算器

1 / 56

第一章 软件总体设计
迷你计算器是一款操作简便而又实用的计算器软件, 它可以被广泛的应用于 各种类型的计算中。 开发此迷你计算器软件的目的为了克服传统计算器软件中遇 到的诸如计算效率低, 难以突破长度限制等问题, 根据对现有计算器软件的分析, 确定了该系统需实现以下功能: 1、二进制、八进制、十进制及十六进制数的加、减、乘、除、乘方、取模 等简单计算; 2、科学计算函数,包括(反)正弦、(反)余弦、(反)正切、(反)余切、开方、 指数等函数运行; 3、以角度、弧度两种方式实现上述部分函数; 4、具备历史计算的记忆功能; 5、对不正确的表达式能指出其错误原因;

1.系统功能模块图
本软件流程图如 图 1.1-1 所示:

2.各类间关系
本软件共使用三个类:CAboutDlg,CCalaApp,CCalaDlg。 其中类 CAboutDlg 描述本软件的作者、 使用方法、 版本信息等, 类 CCalaApp 生成静态的提示文件,类 CCalaDlg 控制主程序。 它们之间的关系如图 1.1-2 所示:
类 CCalaDlg

类 CCalaApp

类 CAboutDlg

图 1.1-2 各类之间的关系

2 / 56

开始

输入数据子函数

双目运算符

单目运算符

编辑框关联的变 量保存至 num2

输入数据子函数

进行运算

运算是否合法 Y 把结果保存到 num2

N

弹出对话框显 示 ERROR

是否用保存的结 果继续进行运算

m_num 清零

N 是否开始新一轮 的计算

N 结束 jie 图 1.1-1 迷你计算器 流程图

3 / 56

第二章 详细设计
本软件主要功能包括:计算器的运算、关于计算器的说明等。 其中功能计算器的运算使用类 CCalaDlg 来实现,功能关于计算器的说明使 用类 CCalaApp 和类 CAboutDlg 来实现。下面分别介绍类 A,B 的详细设计。

1.总体设计
本程序在设计时,参照了 Windows 自带的科学计算器的界面设计和功能模 式。在界面上与其非常相似,如下图所示:

图 2.1-1 程序主界面 利用 Visual C++ 6.0 编程环境,建立基于对话框的 MFC 应用程序,sin、cos 等函数运算统一通过建立按钮相应响应函数实现。在输入的处理上,按钮 0-9 和 A-F 的响应分别由 OnClickedNumber 和 OnClickedNumberAF 来统一响应, 而不是每个按钮都去建立事件单独处理。只需在相关区域加入代码: ON_COMMAND_RANGE(IDC_BTN_0, IDC_BTN_9, OnClickedNumber)

4 / 56

ON_COMMAND_RANGE(IDC_BTN_A, IDC_BTN_F, OnClickedNumberAF) 就可以了,这样不公节省了代码量,而且还使程序更简洁,更通俗易懂。 程序的内核采用栈来处理, 从而不仅可以处理表达式,而且可以按优先级来 计算。 在算符优先级的比较方面,本程序抛弃了传统的建立一个二维数组的方式 来查询比较算符优先级,而是设一个 ENUM 类型的变量,将优先级别小的操作 符放在前面,优先级别大的操作符放在后面,如: enum Operator { OpNone=0,OpAdd,OpSub,OpMul,OpDiv} 这样就可以通过直接比较操作符优先级而进行操作了。

2.部分函数调用关系
表 2.1-1 部分函数调用关系表 Input ClickNumber OnClickedNumber Disp Disp16 Disp8 Disp2 ClickAToF OnClickedNumberAF Disp Input Disp16 Disp8 Disp2 EnableH CCaleDlg OnRadioH SetRadio Disp16 SetRadio ClearS Init ClearP Disp16 Disp Disp8 Disp2 LongType LongType LongType

5 / 56

Func Run OnBtnAdd Disp

GetTwo Disp16 Disp8 Disp2 LongType

3.相关函数和变量说明
文件: Stack.h:栈的基本操作头文件

变量: Bool mustpop:表示是否连续输入两次操作符,mustpop 为 TRUE 时必须从 栈中抛出一个操作符再将本操作符进栈 Bool isopr:用于判断输入的是否为操作符,其值会影响 mustpop 的值 Bool left:用于统计左括号的层数,其值会在程序界面上显示 Stack<double> s:用于存放操作数的栈 Stack<Operator> p:用于存放操作符的栈,Operator 为自定义的枚举类型变 量,保存了所有的操作符 Double m_memval:用于保存记忆数值 Int m_dot:是否有小数点 Int m_bits:小数点位数 Double m_accum:历史操作结果 Double m_operand:当前输入操作数 Bool m_operable:为直时显示当前输入值,为假时显示历史操作结果 Int m_hyp:是否选中双曲函数复选框,取值 0 或 1,与 Hyp 复选框关联 Int m_inv:是否选中反三角函数复选框,取值 0 或 1, ,与 Inv 复选框关联 Int m_2z,m_1z,m_zj:取值 0 或 1,与单先框双字,单字,字节关联 CString m_str:显示字符串,与输出结果框进行关联 Int m_mod:进制类型,取值 16、10、8 或者 2

6 / 56

函数: int GetTwo(double& op1, double& op2):从操作数栈中取出两个操作数 void Func(Operator opp):调用 GetTwo 取出两个数进行 opp 运算 void ClickAToF(int lm):输入 A 到 F 时数值处理,被 OnClickedNumber 调用 void ClickNumber(int lm):输入 0 到 9 时数值处理,被 OnClickedNumberAF

调用 void Init():初始化函数 void ClearP():清空操作符栈 void ClearS():清空操作数栈 void Input(int l, int lm):十六进制,八进制,二进制时按字长度输入 void Run():程序核心,按优先级运算 void Disp2():显示为二进制形式 void Disp8():显示为八进制形式 void Disp16():显示为十六进制形式 void Disp():显示为十进制形式 void LongType():十六进制,八进制,二进制时按字长处理 void EnableB():控制二进制时按钮的可用与不可用状态 void EnableO():控制八进制时按钮的可用与不可用状态 void EnableD():控制十进制时按钮的可用与不可用状态 void EnableH():控制十六进制时按钮的可用与不可用状态 afx_msg void OnClickedNumber(UINT nID):输入数字键响应函数 afx_msg void OnClickedNumberAF(UINT nID):输入 A 到 F 响应函数

4.详细设计
双击课程设计根目录\迷你计算器.exe 执行应用程序, 启动后默认为十进制形 式,可以通过单击显示框下面的四个进制转换单选框切换到不同的进制模式:

7 / 56

十六进制:

十进制:

8 / 56

八进制:

二进制:

9 / 56

1)、数值输入和显示

本程序数据的输入统一由 OnClickedNumber 和 OnClickedNumberAF 两个函 数响应,按照进制相应的位权输入到变量 m_operand 中,显示框根据 m_operand 的值转换到字符串 m_str 显示出来。输入时如果数值超过 1016 时则以科学计数 法表示,输出时也一样。 对于操作符的输入,连续输入两个操作符时按一个计算,连续输入多个操 作符以最后输入的那个为准。
2)、进制转换

本程序对于十进制与十六进制、八进制并没有设计相应的进制转换函数, 当一个数用%X 输出时,则为十六进制,当用%O 输出时则为 8 进制。输出为二 进制时用模 2 的方法转换为一个个的字符输出。
3)、双字单字和字节

在十六进制、八进制和二进制的情况下可以按双字、单字和字节三种类型 显示。显示模式转换时,双字则以无符号长整型将运算结果格式化后输出,单字 以无符号整型将运算结果格式化后输出,字节以字符型将运算结果格式化后输 出,从而达到可选长度输出效果。
4)、记忆系统

计算操作时可以把中间结果或者输入值保存起来, MS 保存,MR 调出, MC 清空,M+把当前值与原值相加后再保存。
5)、退格

为了方便使用,输入错误时可以按退格键删除多余的位。
6)、Inv

程序中 Inv 可以与 sin、cos、tan、cot 等三角函数配合,完成反三角函数运 算,可以与 x2、x3,xy 配合,完成开方运算。

10 / 56

7)、键盘快捷键

因为本程序是基于对话框的应用程序,设快捷键表似乎对程序不起作业, 于是我便在程序的 PreTranslateMessage 函数中动态截获键盘消息调用相应响应 函数进行处理,该函数代码如下: BOOL CCalcDlg::PreTranslateMessage(MSG* pMsg) { // TODO: Add your specialized code here and/or call the base class if(IsDialogMessage(pMsg)) { if(pMsg->message==WM_KEYDOWN) { if(pMsg->wParam==VK_NUMPAD0 ) ClickNumber(0); else if(pMsg->wParam==VK_NUMPAD1) ClickNumber(1); if(m_mod!=2) { if(pMsg->wParam==VK_NUMPAD2) ClickNumber(2); else if(pMsg->wParam==VK_NUMPAD3) ClickNumber(3); else if(pMsg->wParam==VK_NUMPAD4) ClickNumber(4); else if(pMsg->wParam==VK_NUMPAD5) ClickNumber(5); else if(pMsg->wParam==VK_NUMPAD6) ClickNumber(6); else if(pMsg->wParam==VK_NUMPAD7) //键盘快捷键

11 / 56

ClickNumber(7); if(m_mod!=8) { if(pMsg->wParam==VK_NUMPAD8) ClickNumber(8); else if(pMsg->wParam==VK_NUMPAD9) ClickNumber(9); } } if(m_mod==16) { if(pMsg->wParam=='A') ClickAToF(0); else if(pMsg->wParam=='B') ClickAToF(1); else if(pMsg->wParam=='C') ClickAToF(2); else if(pMsg->wParam=='D') ClickAToF(3); else if(pMsg->wParam=='E') ClickAToF(4); else if(pMsg->wParam=='F') ClickAToF(5); } if(pMsg->wParam==VK_SUBTRACT) OnBtnSub(); else if(pMsg->wParam==VK_ADD) OnBtnAdd();

12 / 56

else if(pMsg->wParam==VK_MULTIPLY) OnBtnMul(); else if(pMsg->wParam==VK_DIVIDE) OnBtnDiv(); else if(pMsg->wParam==VK_DECIMAL) OnBtnP(); else if(pMsg->wParam==VK_RETURN) OnBtnBe(); else if(pMsg->wParam==VK_BACK) OnBtnBp(); } return TRUE; } return CDialog::PreTranslateMessage(pMsg); }
8)、程序核心

本程序的核心为两件函数,Run 处理操作数和操作符的栈操作,Func 取出 两个操作数正行运算,程序代码如下: void CCalcDlg::Run() //运算表达式 { Operator play; if(p.stackempty( )||(m_operator==OpLeft)||m_operator>p.peek( )) { if( m_operator==OpLeft) p.push(m_operator); else{ if(m_mustpop) { s.pop(); p.pop(); } p.push(m_operator);

13 / 56

s.push(m_operand); } } else{ if(m_mustpop) { s.pop(); p.pop(); } s.push(m_operand); while (!p.stackempty( )&&m_operator<=p.peek( )) { play=p.pop( ); Func(play); } p.push(m_operator); } if(!s.stackempty( )) { m_operand=m_accum=s.peek( ); Disp( ); } if(m_operator==OpNone) { ClearP( ); ClearS( ); } } void CCalcDlg::Func(enum Operator opp) //从栈中取出两个数进行运算 { double op1,op2; int result; result=GetTwo(op1,op2); if(result) { switch(opp) { case OpAdd: s.push(op1+op2);break; case OpMul: s.push(op1*op2);break; case OpSub: s.push(op2-op1);break;

14 / 56

case OpDiv: if(op1==0) m_str="除数不能为零"; else s.push(op2/op1); break; case OpMod: if(op1==0) m_str="不能对零求模"; else s.push((int)op2%(int)op1); break; case OpPow: double m; if (m_inv) { if(op2>=0) { m=pow(op2,1.0/op1); s.push(m); } else m_str="负数不能开方"; m_inv=FALSE; } else { m=pow(op2,op1); s.push(m); } break; } } else { ClearS( ); ClearP( ); } m_operable=FALSE; m_inv=FALSE; UpdateData(FALSE); }

15 / 56

第三章 系统测试
1.测试方法
采用数学运算进行测试。

2.测试用例
本系统采用数学运算字符为数据原型进行测试,所用数据为: 10+20*(30+40)+sin30。/22 : 123456789*987654321: sin36.5,~sin0.963,~sin1.2:

3.测试结果
1、计算表达式 10+20*(30+40)+sin30。/22 : 计算器输出: 十进制:1410.125 十六进制双字:582 八进制双字:2602 二进制双字:10110000010 实际计算结果:1410.125,与计算结果符合。 2、计算:123456789*987654321: 计算器输出: 十进制:1.219326E+017 十六进制双字:FBFF5380 八进制双字:37377651600 二进制双字:11111011111111110101001110000000 实际计算结果:1.219326311E+017,与计算结果基本符合。 3、计算:sin36.5,~sin0.963,~sin1.2: 计算器输出: 0.594823,74.365401,SIN 函数参数过大

实际计算结果:0.594822786,74.3654011,无法计算,与计算结果基本 符合。 由于程序中采用双精度 Double 型数据,最大有效位为 16 位,最大小数位数 为 6 位。同时十六进制、八进制和二进制没有设置小数处理。
16 / 56

第四章 软件使用说明书
1.系统运行环境
Windows XP、 Windows 7、 Windows 8、 8.1 (Windows NT 以及 Windows 2000 未进行测试,请在专业人员的指导下使用,以防对计算机造成不确定的伤害) 。

2.程序主要功能
该程序需实现以下功能: 1) 、二进制、八进制、十进制及十六进制数的加、减、乘、除、乘方、取 模等简单计算; 2) 、科学计算函数,包括(反)正弦、(反)余弦、(反)正切、(反)余切、开 方、指数等函数运行; 3) 、以角度、弧度两种方式实现上述部分函数; 4) 、具备历史计算的记忆功能; 5) 、对不正确的表达式能指出其错误原因;

3.使用说明
1)、Sin、Cos、Tan、Log、Mod、阶乘、指数、对数等运算先输入数值再按 相应键计算 2)、Hyp 与 Sin、Cos 和 Tan 配合,选中为计算双曲函数 3)、Inv 可与三角函数、指数、对数等键配合,选中为计算反三角函数、开 方、指数应算 4)、Log 应算以 10 为底,Ln 应算以 e 为底 5)、CE 为清空当前值,C 为全部清空 6)、MC:清空存储数据;MR:调出存储数据;MS:保存当前数据;M+: 将当前数据累加到已存储的数据中 此迷你计算器的使用方法和 Windows 7 自带计算器的使用方法完全相同, 和日常生活中的亦同,使用者可灵活使用。

17 / 56





课程设计是培养学生综合运用所学知识 ,发现,提出,分析和解决实际问题,锻 炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程.随着科学 技术发展的日新日异, 当今计算机应用在生活中可以说得是无处不在。因此作为 二十一世纪的大学来说掌握计算机开发技术是十分重要的。 回顾起此次课程设计,至今让我我们仍感慨颇多,的确,从从拿到题目到完 成整个编程,从理论到实践,两个星期的日子里,可以学到很多很多的的东西, 同时不仅可以巩固了以前所学过的知识, 而且学到了很多在书本上所没有学到过 的知识, 也懂得集体团队的重要性。通过这次课程设计使我懂得了理论与实际相 结合是很重要的, 只有理论知识是远远不够的,只有把所学的理论知识与实践相 结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手 能力和独立思考的能力。在设计的过程中遇到问题,可以说得是困难重重,这毕 竟第二次做的, 难免会遇到过各种各样的问题,同时在设计的过程中发现了自己 的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固,比如说结 构体……通过这次课程设计之后,一定把以前所学过的知识重新温故。

18 / 56

参考文献
[1].何钦铭.陈根才面向对象程序设计 课程设计.浙江: 浙江大学出版社, 2008 [2].任海军 余健 夏崇镨.Visual C++课程设计 案例精编.北京: 清华大学出版 社,2008 [3].黄金明. Visual C++6.0 基础与实例教程.北京:中国电力出版社,2007 [4].朱金付 柏毅.C++课程设计.北京:清华大学出版社,2011

19 / 56

致谢
本学期学习了 C++语言,对 Visual C++ 6.0 编程环境也有一定的了解。但是 了解的只是一点皮毛而已, 而且这么长时间都没有去复习,相关的知识也忘得差 不多了。经过这次课程设计,我重新复习了一下相关知识,加深了对 Visual C++ 的理解。对 Visual C++的运行机制、类、消息处理等的理解都有了明显的提高, 对编译时产生的错误能够迅速地找出原因所在。 一开始的时候很讨厌 MFC,因为我觉得用它来写程序一点都不方面,一大 堆的类,一大堆的调用关系,定制性还很差,是一个古懂级的编程环境。但是后 来才发现其实并不是这样子的。对 MFC 的运行和操作机制有一定了解后你会发 现,其实 MFC 也有他的优点,用 MFC 来写程序也是很愉快的事情。如果你有 能力,你同样可以把一个程序写得很好。 紧张又忙碌的课设学习终于结束了,在本次课设中我们也取得了很大的成 就。在此衷心感谢学院安排这次课设,让我们又多了一次交流学习的机会,更好 的巩固了所学知识,拓展了知识面。 在编写程序的过程中, 我们得到了年福忠等三位老师的精心指导以及孜孜不 倦的教诲,在老师的指导下,我们的能力得到了提高,同时养成了科学、严谨的 作风和习惯,在此,我们对老师的精心栽培表示衷心的感谢!也感谢我们专业同 学在非常时期,在生活和学习上对我的帮助和指点。同时,也要感谢互联网的大 力帮助。

20 / 56

附件:程序原代码
1.calcDlg.cpp
// calcDlg.cpp : implementation file // #include "stdafx.h" #include "calc.h" #include "calcDlg.h" #include "math.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg)
21 / 56

// DDX/DDV

afx_msg void OnLButtonDown(UINT nFlags, CPoint point); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) ON_WM_LBUTTONDOWN() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CCalcDlg dialog CCalcDlg::CCalcDlg(CWnd* pParent /*=NULL*/) : CDialog(CCalcDlg::IDD, pParent) { //{{AFX_DATA_INIT(CCalcDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CCalcDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CCalcDlg) // NOTE: the ClassWizard will add DDX and DDV calls here

22 / 56

//}}AFX_DATA_MAP DDX_Text(pDX, IDC_DISPLAY, m_str); DDX_Check(pDX, IDC_CHECK_INV, m_inv); DDX_Check(pDX, IDC_CHECK_HYP, m_hyp); DDX_Check(pDX, IDC_RADIO_2Z, m_2z); DDX_Check(pDX, IDC_RADIO_1Z, m_1z); } BEGIN_MESSAGE_MAP(CCalcDlg, CDialog) //{{AFX_MSG_MAP(CCalcDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_COMMAND(ID_MENU_ABOUT, OnMenuAbout) ON_BN_CLICKED(IDC_RADIO_H, OnRadioH) ON_BN_CLICKED(IDC_RADIO_D, OnRadioD) ON_BN_CLICKED(IDC_RADIO_O, OnRadioO) ON_BN_CLICKED(IDC_RADIO_B, OnRadioB) ON_BN_CLICKED(IDC_CHECK_INV, OnCheckInv) ON_BN_CLICKED(IDC_CHECK_HYP, OnCheckHyp) ON_BN_CLICKED(IDC_BTN_P, OnBtnP) ON_BN_CLICKED(IDC_BTN_BE, OnBtnBe) ON_BN_CLICKED(IDC_BTN_ADD, OnBtnAdd) ON_BN_CLICKED(IDC_BTN_SUB, OnBtnSub) ON_BN_CLICKED(IDC_BTN_MUL, OnBtnMul) ON_BN_CLICKED(IDC_BTN_DIV, OnBtnDiv) ON_BN_CLICKED(IDC_BTN_M, OnBtnM) ON_BN_CLICKED(IDC_BTN_1x, OnBTN1x) ON_BN_CLICKED(IDC_BTN_AS, OnBtnAs) ON_BN_CLICKED(IDC_RADIO_2Z, OnRadio2z) ON_BN_CLICKED(IDC_RADIO_1Z, OnRadio1z) ON_BN_CLICKED(IDC_BTN_XY, OnBtnXy) ON_BN_CLICKED(IDC_BTN_X2, OnBtnX2) ON_BN_CLICKED(IDC_BTN_X3, OnBtnX3) ON_BN_CLICKED(IDC_BTN_N, OnBtnN) ON_BN_CLICKED(IDC_BTN_LOG, OnBtnLog) ON_BN_CLICKED(IDC_BTN_LN, OnBtnLn) ON_BN_CLICKED(IDC_BTN_TAN, OnBtnTan) ON_BN_CLICKED(IDC_BTN_COS, OnBtnCos) ON_COMMAND_RANGE(IDC_BTN_0, IDC_BTN_9, OnClickedNum) ON_COMMAND_RANGE(IDC_BTN_A, IDC_BTN_F, OnClickedAF)

23 / 56

ON_BN_CLICKED(IDC_BTN_C, OnBtnC) ON_BN_CLICKED(IDC_BTN_CE, OnBtnCe) ON_BN_CLICKED(IDC_BTN_PI, OnBtnPi) ON_BN_CLICKED(IDC_BTN_MC, OnBtnMc) ON_BN_CLICKED(IDC_BTN_MR, OnBtnMr) ON_BN_CLICKED(IDC_BTN_MS, OnBtnMs) ON_BN_CLICKED(IDC_BTN_MA, OnBtnMa) ON_BN_CLICKED(IDC_BTN_BP, OnBtnBp) ON_BN_CLICKED(IDC_BTN_SIN, OnBtnSin) ON_BN_CLICKED(IDC_BTN_SQRT, OnBtnCot) ON_COMMAND(ID_MENU_EXIT, OnMenuExit) ON_BN_CLICKED(IDC_BTN_LEFT, OnBtnLeft) ON_BN_CLICKED(IDC_BTN_RIGHT, OnBtnRight) ON_COMMAND(ID_MENU_VIEW, OnMenuView) ON_COMMAND(ID_MENU_HELP, OnMenuHelp) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CCalcDlg message handlers BOOL CCalcDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); }

24 / 56

} // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here //初始化 CFont* m_Font; //设置字体 m_Font = new CFont; GetDlgItem(IDC_DISPLAY)->SetFont(m_Font,FALSE); delete m_Font; CheckDlgButton(IDC_RADIO_D,1); CheckDlgButton(IDC_RADIO_2Z,1); Init(); OnRadioD(); m_memval=0; m_isopr=FALSE; m_mustpop=FALSE; GetDlgItem(IDC_BTN_BE)->SetFocus(); return TRUE; // return TRUE unless you set the focus to a control } void CCalcDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } }

25 / 56

// If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CCalcDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CCalcDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } void CCalcDlg::OnMenuAbout() { // TODO: Add your command handler code here CAboutDlg dlg; dlg.DoModal(); (WPARAM)

26 / 56

} void CAboutDlg::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CDialog::OnOK(); CDialog::OnLButtonDown(nFlags, point); } void CCalcDlg::OnRadioH() //十六进制 { // TODO: Add your control notification handler code here m_mod=16; EnableH(); SetRadio(); m_operable=FALSE; m_accum=m_operand; Disp16(); } void CCalcDlg::SetRadio() { if(m_mod==10){ GetDlgItem(IDC_RADIO_2Z)->SetWindowText("角度"); GetDlgItem(IDC_RADIO_1Z)->SetWindowText("弧度"); }else if(m_mod!=10){ GetDlgItem(IDC_RADIO_2Z)->SetWindowText("双字"); GetDlgItem(IDC_RADIO_1Z)->SetWindowText("单字"); } m_zj=0; m_2z=1; m_1z=0; UpdateData(FALSE); } void CCalcDlg::OnRadioD() //十进制 { // TODO: Add your control notification handler code here m_mod=10;

27 / 56

EnableD(); SetRadio(); m_operable=FALSE; m_accum=m_operand; Disp(); } void CCalcDlg::OnRadioO() //八进制 { // TODO: Add your control notification handler code here m_mod=8; EnableO(); SetRadio(); m_operable=FALSE; m_accum=m_operand; Disp(); } void CCalcDlg::OnRadioB() //二进制 { // TODO: Add your control notification handler code here m_mod=2; EnableB(); SetRadio(); m_operable=FALSE; m_accum=m_operand; Disp(); } void CCalcDlg::OnCheckInv() //Inv { // TODO: Add your control notification handler code here m_inv=!m_inv; } void CCalcDlg::EnableH() //十六进制模式 { int i; for(i=0;i<=7;i++) { GetDlgItem(IDC_BTN_2+i)->EnableWindow(TRUE); }

28 / 56

for(i=0;i<=6;i++) { GetDlgItem(IDC_BTN_A+i)->EnableWindow(TRUE); } GetDlgItem(IDC_BTN_SIN)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_COS)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_TAN)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_PI)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_BE)->EnableWindow(TRUE); } void CCalcDlg::EnableD() //十进制模式 { int i; for(i=0;i<=7;i++) { GetDlgItem(IDC_BTN_2+i)->EnableWindow(TRUE); } for(i=0;i<=6;i++) { GetDlgItem(IDC_BTN_A+i)->EnableWindow(FALSE); } GetDlgItem(IDC_BTN_SIN)->EnableWindow(TRUE); GetDlgItem(IDC_BTN_COS)->EnableWindow(TRUE); GetDlgItem(IDC_BTN_TAN)->EnableWindow(TRUE); GetDlgItem(IDC_BTN_PI)->EnableWindow(TRUE); GetDlgItem(IDC_BTN_BE)->EnableWindow(TRUE); } void CCalcDlg::EnableO() //八进制模式 { int i; for(i=0;i<=5;i++) { GetDlgItem(IDC_BTN_2+i)->EnableWindow(TRUE); } GetDlgItem(IDC_BTN_8)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_9)->EnableWindow(FALSE); for(i=0;i<=6;i++) {

29 / 56

GetDlgItem(IDC_BTN_A+i)->EnableWindow(FALSE); } GetDlgItem(IDC_BTN_SIN)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_COS)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_TAN)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_PI)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_BE)->EnableWindow(TRUE); } void CCalcDlg::EnableB() //二进制模式 { int i; for(i=0;i<=7;i++) { GetDlgItem(IDC_BTN_2+i)->EnableWindow(FALSE); } for(i=0;i<=6;i++) { GetDlgItem(IDC_BTN_A+i)->EnableWindow(FALSE); } GetDlgItem(IDC_BTN_SIN)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_COS)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_TAN)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_PI)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_BE)->EnableWindow(TRUE); } void CCalcDlg::OnCheckHyp() //Hyp { // TODO: Add your control notification handler code here m_hyp=!m_hyp; } void CCalcDlg::LongType() //二进制,八进制,十六进制长度 { unsigned long int lVal = (m_operable) ?(unsigned long int)m_operand : (unsigned long int)m_accum; if(m_2z==1) //如果是双字 lVal=(unsigned long int)(lVal); else if(m_1z==1) //如果是字

30 / 56

lVal=(unsigned short)(lVal); else if(m_zj==1) //如果是字节 lVal=(unsigned char)(lVal); m_operand=m_accum=lVal; } void CCalcDlg::Disp() //进制显示转换 { GetDlgItem(IDC_BTN_BE)->SetFocus(); if(m_mod==16) // 将结果由十进制转化为 16 进制 { Disp16( ); } else if(m_mod==8) // 将结果由十进制转化为 8 进制 { Disp8( ); } else if(m_mod==2) // 将结果由十进制转化为二进制 { Disp2( ); }else // 十进制的显示,科学记数法 { double lVal = (m_operable) ? m_operand : m_accum; if(lVal>1.0e+16) { m_str.Format(_T("%e"),lVal); int i=m_str.GetLength( ); } else { m_str.Format(_T("%lf"),lVal); int i=m_str.GetLength( ); while(m_str.GetAt(i-1)=='0') { m_str.Delete(i-1,1); i-=1; } } UpdateData(FALSE); }

31 / 56

} void CCalcDlg::Disp16() //转换为 16 进制显示 { LongType(); unsigned long int lVal = (m_operable) ?(unsigned m_operand :(unsigned long int) m_accum; m_str.Format("%X",(lVal)); UpdateData(FALSE); } void CCalcDlg::Disp8() //转换为八进制显示 { LongType(); unsigned long int lVal = (m_operable) ?(unsigned m_operand :(unsigned long int) m_accum; m_str.Format("%o",(lVal)); UpdateData(FALSE); }

long

int)

long

int)

void CCalcDlg::Disp2() //转换为二进制显示 { LongType(); CString str; m_str=""; unsigned long int lVal = (m_operable) ?(unsigned long int) m_operand : (unsigned long int)m_accum; unsigned long int a=lVal; while((a/2)!=0) { str.Format("%d",a%2); m_str.Insert(0,str); a=a/2; } str.Format("%d",a); m_str.Insert(0,str); UpdateData(FALSE); } void CCalcDlg::OnBtnP() //小数点 { // TODO: Add your control notification handler code here

32 / 56

m_isopr=FALSE; m_dot=TRUE; m_operable=TRUE; } void CCalcDlg::Run() //运算表达式 { Operator play; if(p.stackempty( )||(m_operator==OpLeft)||m_operator>p.peek( )) { if( m_operator==OpLeft) p.push(m_operator); else{ if(m_mustpop) { s.pop(); p.pop(); } p.push(m_operator); s.push(m_operand); } } else{ if(m_mustpop) { s.pop(); p.pop(); } s.push(m_operand); while (!p.stackempty( )&&m_operator<=p.peek( )) { play=p.pop( ); Func(play); } p.push(m_operator); } if(!s.stackempty( )) { m_operand=m_accum=s.peek( ); Disp( ); }

33 / 56

if(m_operator==OpNone) { ClearP( ); ClearS( ); } } void CCalcDlg::OnBtnBe() //等号 { // TODO: Add your control notification handler code here m_isopr=FALSE; m_mustpop=FALSE; m_operable=FALSE; m_operator=OpNone; Run(); } void CCalcDlg::OnBtnAdd() //加 { // TODO: Add your control notification handler code here m_mustpop=m_isopr; m_isopr=TRUE; m_operable=FALSE; m_operator=OpAdd; Run(); } void CCalcDlg::OnBtnSub() //减 { // TODO: Add your control notification handler code here m_mustpop=m_isopr; m_isopr=TRUE; m_operable=FALSE; m_operator=OpSub; Run(); } void CCalcDlg::OnBtnMul() //乘 { // TODO: Add your control notification handler code here

34 / 56

m_mustpop=m_isopr; m_isopr=TRUE; m_operable=FALSE; m_operator=OpMul; Run(); } void CCalcDlg::OnBtnDiv() //除 { // TODO: Add your control notification handler code here m_mustpop=m_isopr; m_isopr=TRUE; m_operable=FALSE; m_operator=OpDiv; Run(); } void CCalcDlg::OnBtnM() //计算 Mod { // TODO: Add your control notification handler code here m_isopr=FALSE; m_operable=FALSE; m_operator=OpMod; Run(); } void CCalcDlg::OnBTN1x() //求倒数 { // TODO: Add your control notification handler code here m_isopr=FALSE; double t; t=m_operand; if(t) { t=1.0/t; m_operable=FALSE; m_accum=m_operand=t; Disp( ); } }

35 / 56

void CCalcDlg::OnBtnAs() //+/{ // TODO: Add your control notification handler code here m_isopr=FALSE; m_accum=m_operand=(-1)*m_operand; m_operable=FALSE; Disp(); } void CCalcDlg::Input(int l,int lm) //二进制,八进制,十六进制的输入 { double a; a=m_operand*l+lm; if(m_2z==1) if( a<=4294967295) m_operand=a; if(m_1z==1) if( a<=65535) m_operand=a; if (m_zj==1) if( a<=255) m_operand=a; } void CCalcDlg::OnRadio2z() //双字 { // TODO: Add your control notification handler code here m_2z=1; m_1z=0; m_zj=0; m_accum=m_operand; m_operable=FALSE; Disp(); } void CCalcDlg::OnRadio1z() //单字 { // TODO: Add your control notification handler code here m_2z=0; m_1z=1; m_zj=0; m_accum=m_operand; m_operable=FALSE; Disp(); } void CCalcDlg::OnRadioZj() //字节 { // TODO: Add your control notification handler code here

36 / 56

m_2z=0; m_1z=0; m_zj=1; m_accum=m_operand; m_operable=FALSE; Disp(); } void CCalcDlg::ClearS() { s.clearstack( ); } void CCalcDlg::ClearP() { p.clearstack( ); } //清空数据栈

//清空操作栈

void CCalcDlg::Init() //初始化函数 { m_operand = 0; m_operator = OpNone; m_accum = 0; m_dot=0; m_bits=0; m_left=0; m_operable=FALSE; m_isopr=FALSE; m_mustpop=FALSE; m_inv=0; m_hyp=0; m_strleft.Format("%s"," "); UpdateData(FALSE); ClearS(); ClearP(); Disp( ); } void CCalcDlg::ClickNum(int lm) { m_isopr=FALSE; if (!m_operable) //从 0 开始 { //输入 0 到 9

37 / 56

m_operand = 0L; m_dot=0; m_bits=0; } if(m_mod==10) { if(m_dot) { m_bits++; m_operand=m_operand+lm/pow(10,m_bits); } else m_operand=m_operand*10+lm; } if(m_mod==16) Input(16,lm); if(m_mod==8) Input(8,lm); if(m_mod==2) Input(2,lm); m_operable=TRUE; Disp(); } void CCalcDlg::OnBtnXy() //求 N 次方 { // TODO: Add your control notification handler code here m_isopr=FALSE; m_operator=OpPow; m_operable=FALSE; Run( ); } void CCalcDlg::OnBtnX2() //求平方 { // TODO: Add your control notification handler code here m_isopr=FALSE; double t; t=m_operand; if(m_inv) { if(t>=0) { t=pow(t,1.0/2); m_accum=m_operand=t;

38 / 56

Disp( ); }else { m_str="负数不能开平方"; m_accum=m_operand=0; } m_inv=FALSE; UpdateData(FALSE); }//二次方根 else { t=pow(t,2); m_accum=m_operand=t; Disp( ); } m_operable=FALSE; } void CCalcDlg::OnBtnX3() //求立方 { // TODO: Add your control notification handler code here m_isopr=FALSE; double t; t=m_operand; if(m_inv) { if(t>=0) { t=pow(t,1.0/3); m_accum=m_operand=t; Disp( ); }else { m_str="负数不能开立方"; m_accum=m_operand=0; } m_inv=FALSE; UpdateData(FALSE); }//三次方根 else

39 / 56

{ t=pow(t,3); m_accum=m_operand=t; Disp( ); } m_operable=FALSE; } void CCalcDlg::OnBtnN() //阶乘 { // TODO: Add your control notification handler code here m_isopr=FALSE; int i; long fa=1; for(i=1;i<=m_operand;i++) fa*=i; m_operand=fa; m_operable=FALSE; m_accum=m_operand; Disp( ); } void CCalcDlg::OnBtnLog() //计算 Log { // TODO: Add your control notification handler code here m_isopr=FALSE; if(m_operand==0) { m_str="对数不能为零"; m_inv=FALSE; UpdateData(FALSE); } else { if(m_inv) m_operand=pow(10,m_operand); else m_operand=log10(m_operand); m_inv=FALSE; UpdateData(FALSE);

40 / 56

Disp( ); } m_operable=FALSE; m_accum=m_operand; } void CCalcDlg::OnBtnLn() //计算 Ln { // TODO: Add your control notification handler code here m_isopr=FALSE; if(m_operand==0) { m_str="对数不能为零"; m_inv=FALSE; UpdateData(FALSE); } else { if(m_inv) m_operand=exp(m_operand); else m_operand=log(m_operand); m_inv=FALSE; UpdateData(FALSE); Disp( ); } m_operable=FALSE; m_accum=m_operand; } void CCalcDlg::OnBtnTan() //求 Tan { // TODO: Add your control notification handler code here m_isopr=FALSE; if(m_2z==1&&!m_hyp&&!m_inv) m_operand=m_operand/180*pi; if(!m_inv&&!m_hyp) m_operand=tan(m_operand); else if(m_inv) m_operand=atan(m_operand); else if(m_hyp) m_operand=tanh(m_operand); if(m_inv&&m_2z==1) m_operand=m_operand*180/pi;

41 / 56

m_accum=m_operand; m_inv=m_hyp=FALSE; m_operable=FALSE; UpdateData(FALSE); Disp(); } void CCalcDlg::OnBtnCos() //计算 Cos { // TODO: Add your control notification handler code here m_isopr=FALSE; if(m_2z==1&&!m_hyp&&!m_inv) m_operand=m_operand/180*pi; if(!m_inv&&!m_hyp) m_operand=cos(m_operand); else if(m_inv) m_operand=acos(m_operand); else if(m_hyp) m_operand=cosh(m_operand); if(m_inv&&m_2z==1) m_operand=m_operand*180/pi;

m_accum=m_operand; m_inv=m_hyp=FALSE; m_operable=FALSE; UpdateData(FALSE); Disp(); if(m_operand==-1) { m_str="COS 函数参数不正确"; m_operand=0; UpdateData(FALSE); } } void CCalcDlg::ClickAF(int lm) { m_isopr=FALSE; if (!m_operable) { m_operand = 0L; m_dot=0; m_bits=0; //输入 A 到 F

42 / 56

} if(m_mod==16) Input(16,lm+10); m_operable=TRUE; Disp(); } void CCalcDlg::OnClickedNum(UINT nID) { ASSERT(nID >= IDC_BTN_0 && nID <= IDC_BTN_9); ClickNum(nID - IDC_BTN_0); } void CCalcDlg::OnClickedAF(UINT nID) { ASSERT(nID >= IDC_BTN_A && nID <= IDC_BTN_F); ClickAF(nID - IDC_BTN_A); } void CCalcDlg::OnBtnC() //归零 { // TODO: Add your control notification handler code here Init(); } void CCalcDlg::OnBtnCe() //清零 { // TODO: Add your control notification handler code here m_isopr=FALSE; m_str="0."; m_operable=FALSE; m_operand=0; UpdateData(FALSE); } void CCalcDlg::OnBtnPi() //3.14 { // TODO: Add your control notification handler code here m_isopr=FALSE; if(m_inv) m_operand=3.14159265535897932384*2; else m_operand=3.14159265535897932384;

43 / 56

m_str.Format(_T("%.20f"), m_operand); UpdateData(FALSE); } void CCalcDlg::OnBtnMc() //记忆清空 { // TODO: Add your control notification handler code here m_memval=0L; m_strm=""; UpdateData(FALSE); } void CCalcDlg::OnBtnMr() //调出记忆数据 { // TODO: Add your control notification handler code here m_operand=m_memval; m_operable=TRUE; if(!m_memval) OnBtnMc(); Disp(); } void CCalcDlg::OnBtnMs() //将当前值存入记忆 { // TODO: Add your control notification handler code here double lval = (m_operable) ? m_operand : m_accum; m_memval=lval; if(m_memval!=0) { m_strm="M"; UpdateData(FALSE); } } void CCalcDlg::OnBtnMa() //计忆累加 { // TODO: Add your control notification handler code here m_memval=m_memval+m_operand; if(m_memval==0) OnBtnMc( ); else {

44 / 56

m_strm="M"; UpdateData(FALSE); } m_operable=FALSE; } void CCalcDlg::OnBtnBp() //退格 { // TODO: Add your control notification handler code here if(m_mod==10) { if (m_dot==0) m_operand=(m_operand-((int)(m_operand))%10)/10; else { m_operand=m_operand-(int)((int)(m_operand*pow(10,m_bits))%10)/pow(1 0,m_bits); m_bits--; if (m_bits==0) m_dot=0; } } if(m_mod==16) m_operand=(m_operand-(int)(m_operand)%16)/16; if(m_mod==8) m_operand=(m_operand-(int)(m_operand)%8)/8; if(m_mod==2) m_operand=(m_operand-(int)(m_operand)%2)/2; Disp( ); } void CCalcDlg::OnBtnSin() //计算 Sin { // TODO: Add your control notification handler code here m_isopr=FALSE; if(m_2z==1&&!m_hyp&&!m_inv) m_operand=m_operand/180*pi; if(!m_inv&&!m_hyp) m_operand=sin(m_operand); else if(m_inv) m_operand=asin(m_operand); else if(m_hyp) m_operand=sinh(m_operand); if(m_inv&&m_2z==1) m_operand=m_operand*180/pi;

45 / 56

m_accum=m_operand; m_inv=m_hyp=FALSE; m_operable=FALSE; UpdateData(FALSE); Disp(); if(m_operand==-1) { m_str="SIN 函数参数不正确"; m_operand=0; UpdateData(FALSE); } } void CCalcDlg::OnBtnCot() //求开方 { // TODO: Add your control notification handler code here m_isopr=FALSE; if(m_2z==1&&!m_hyp&&!m_inv) m_operand=m_operand/180*pi; if(!m_inv&&!m_hyp) m_operand=1/tan(m_operand); else if(m_inv) m_operand=atan(1/m_operand); else if(m_hyp) m_operand=tanh(m_operand); if(m_inv&&m_2z==1) m_accum=m_operand; m_inv=m_hyp=FALSE; m_operable=FALSE; UpdateData(FALSE); Disp(); } void CCalcDlg::OnMenuExit() { // TODO: Add your command handler code here CCalcDlg::OnOK(); } void CCalcDlg::OnBtnLeft() //左括号 m_operand=m_operand*180/pi;

46 / 56

{ // TODO: Add your control notification handler code here m_isopr=FALSE; m_left++; m_strleft.Format("%s%d","(=",m_left); UpdateData(FALSE); m_operator=OpLeft; m_operable=FALSE; Run( ); } void CCalcDlg::OnBtnRight() //右括号 { // TODO: Add your control notification handler code here m_isopr=FALSE; if(m_left){ m_operator=OpRight; m_operable=FALSE; m_left--; if (m_left) m_strleft.Format("%s%d","(=",m_left); else m_strleft.Format("%s"," "); UpdateData(FALSE); s.push(m_operand); Operator op; while(p.peek( )!=OpLeft) { op=p.pop( ); Func(op); } m_operand=m_accum=s.peek( ); Disp( ); p.pop( ); s.pop( ); } } void CCalcDlg::Func(enum Operator opp) { double op1,op2; int result; //从栈中取出两个数进行运算

47 / 56

result=GetTwo(op1,op2); if(result) { switch(opp) { case OpAdd: s.push(op1+op2);break; case OpMul: s.push(op1*op2);break; case OpSub: s.push(op2-op1);break; case OpDiv: if(op1==0) m_str="除数不能为零"; else s.push(op2/op1); break; case OpMod: if(op1==0) m_str="不能对零求模"; else s.push((int)op2%(int)op1); break; case OpPow: double m; if (m_inv) { if(op2>=0) { m=pow(op2,1.0/op1); s.push(m); } else m_str="负数不能开方"; m_inv=FALSE; } else { m=pow(op2,op1); s.push(m); } break; } } else

48 / 56

{ ClearS( ); ClearP( ); } m_operable=FALSE; m_inv=FALSE; UpdateData(FALSE); } int CCalcDlg::GetTwo(double &op1, double &op2) { if(s.stackempty( )) return 0; op1=s.pop( ); if(s.stackempty( )) return 0; op2=s.pop( ); return 1; } //从数据栈取出两个数

void CCalcDlg::OnMenuView() { // TODO: Add your command handler code here MessageBox(" 课设报告在文件夹根目录!","迷你计算器 提示",MB_OK); } void CCalcDlg::OnMenuHelp() { // TODO: Add your command handler code here WinExec("notepad 说明.txt",SW_SHOWNORMAL); } BOOL CCalcDlg::PreTranslateMessage(MSG* pMsg) //键盘快捷键 { // TODO: Add your specialized code here and/or call the base class if(IsDialogMessage(pMsg)) { if(pMsg->message==WM_KEYDOWN) { if(pMsg->wParam==VK_NUMPAD0 ) ClickNum(0); else if(pMsg->wParam==VK_NUMPAD1)

49 / 56

ClickNum(1); if(m_mod!=2) { if(pMsg->wParam==VK_NUMPAD2) ClickNum(2); else if(pMsg->wParam==VK_NUMPAD3) ClickNum(3); else if(pMsg->wParam==VK_NUMPAD4) ClickNum(4); else if(pMsg->wParam==VK_NUMPAD5) ClickNum(5); else if(pMsg->wParam==VK_NUMPAD6) ClickNum(6); else if(pMsg->wParam==VK_NUMPAD7) ClickNum(7); if(m_mod!=8) { if(pMsg->wParam==VK_NUMPAD8) ClickNum(8); else if(pMsg->wParam==VK_NUMPAD9) ClickNum(9); } } if(m_mod==16) { if(pMsg->wParam=='A') ClickAF(0); else if(pMsg->wParam=='B') ClickAF(1); else if(pMsg->wParam=='C') ClickAF(2); else if(pMsg->wParam=='D') ClickAF(3); else if(pMsg->wParam=='E') ClickAF(4); else if(pMsg->wParam=='F') ClickAF(5); } if(pMsg->wParam==VK_SUBTRACT) OnBtnSub(); else if(pMsg->wParam==VK_ADD) OnBtnAdd();

50 / 56

else if(pMsg->wParam==VK_MULTIPLY) OnBtnMul(); else if(pMsg->wParam==VK_DIVIDE) OnBtnDiv(); else if(pMsg->wParam==VK_DECIMAL) OnBtnP(); else if(pMsg->wParam==VK_RETURN) OnBtnBe(); else if(pMsg->wParam==VK_BACK) OnBtnBp(); } return TRUE; } return CDialog::PreTranslateMessage(pMsg); }

2.calc.cpp
// calc.cpp : Defines the class behaviors for the application. // #include "stdafx.h" #include "calc.h" #include "calcDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CCalcApp BEGIN_MESSAGE_MAP(CCalcApp, CWinApp) //{{AFX_MSG_MAP(CCalcApp) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG ON_COMMAND(ID_HELP, CWinApp::OnHelp) END_MESSAGE_MAP()

51 / 56

CString CCalcApp::TEMP=""; ///////////////////////////////////////////////////////////////////////////// // CCalcApp construction CCalcApp::CCalcApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance } ///////////////////////////////////////////////////////////////////////////// // The one and only CCalcApp object CCalcApp theApp; ///////////////////////////////////////////////////////////////////////////// // CCalcApp initialization BOOL CCalcApp::InitInstance() { AfxEnableControlContainer(); // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need. #ifdef _AFXDLL Enable3dControls(); // Call this when using MFC in a shared DLL #else Enable3dControlsStatic(); // Call this when linking to MFC statically #endif CCalcDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: Place code here to handle when the dialog is // dismissed with OK } else if (nResponse == IDCANCEL)

52 / 56

{ // TODO: Place code here to handle when the dialog is // dismissed with Cancel } // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. return FALSE; }

3.其他代码及头文件
其他源文件详见光盘:计算机一班 \12240110 刘海龙 \迷你计算器 源文件 (MFC)\ 文件夹。

53 / 56


相关文章:
迷你计算器设计.doc
迷你计算器设计 - 单片机C语言课程设计迷你计算器设计... 《嵌入式系统》课程设计说明书 迷你计算器设计院 、部: 学生姓名 湖南工学院嵌入式系统课程设计课题任务书...
迷你计算器设计3.doc
迷你计算器设计3 - 单片机C语言课程设计迷你计算器设计... 《嵌入式系统》课程设计说明书 迷你计算器设计院 、部: 学生姓名: 指导教师: 专班学业: 级: 号: 完...
迷你计算器设计说明书.doc
public calculator() { super("迷你计算器");//设置标题栏 df = new DecimalFormat();//保留四位小数 this.setLayout(new BorderLayout(10, 5)); panel1 ...
05-迷你计算器设计.doc
05-迷你计算器设计 - 计算机科学与技术本科专业 Java 课程设计任务书 (12 级) 题目:迷你计算器设计 学生姓名: 题目类型:软件工程(R) 一. 题目简介 学号: ...
迷你计算器.doc
迷你计算器 - 1 *** 实践教学 *** 兰州理工大学 计算机与通信学院 2
项目2 迷你计算器_图文.ppt
项目2 迷你计算器 - 项目2 迷你计算器 ? 本项目学习目标 ? 掌握Visu
迷你计算器说明书.doc
迷你计算器说明书 - 目摘前正 1. 2. 3. 4. 5. 6. 总 录 要
迷你计算器设计说明书.doc
迷你计算器设计说明书 - *** 实践教学 *** 兰州理工大学 计算机与通信学
迷你计算器源码完整版(Builder C++ 6.0).doc
迷你计算器源码完整版(Builder C++ 6.0) - //---...
迷你计算器设计.doc
迷你计算器设计 - *** 实践教学 *** 兰州理工大学 计算机与通信学院 2
13-迷你计算器设计.doc
13-迷你计算器设计 - 信息与计算科学本科专业 数据结构课程设计任务书 (10 级) 题目:迷你计算器设计 学生姓名: 班级: 题目类型:软件工程(R) 指导教师: 学号:...
迷你计算器说明书.doc
迷你计算器说明书 - *** 实践教学 *** 兰州理工大学 计算机与通信学院
10-迷你计算器设计.doc
10-迷你计算器设计 - 计算机科学与技术本科专业 Java 课程设计任务书 (10 级) 题目:迷你计算器设计 学生姓名: 班级: 题目类型:软件工程(R) 一. 题目简介 ...
中国迷你计算器行业市场调查研究报告(目录)_图文.doc
中国迷你计算器行业市场调查研究报告(目录) - 中经视野市场调查研究报告内容主要
迷你计算器项目可行性研究报告(目录)_图文.doc
迷你计算器项目可行性研究报告(目录) - 迷你计算器项目 可行性研究报告 千讯(北京)信息咨询有限公司 http://www.qianinfo.com 《迷你计算器项目可行性研究报告》 ...
迷你计算器数据结构课程设计报告.doc
迷你计算器数据结构课程设计报告 - 数据结构课程设计报告 题目: 迷你计算器 一、课程设计题目:迷你计算器 二、问题定义: (由教师指定) 功能要求: ( 1 )计算...
开发一个简单计算器程序-基于对话框.doc
开发一个简单计算器程序-基于对话框 - 开发一个简单科学计算器 (基于对话框模式的应用程序) 一. 开发目标及软件功能 开发一个科学计算器程序, 要求采用基于对话...
计算机 计算器迷你价格.doc
计算机 计算器迷你价格 - 慧采科技 http://www.quandeli.com 宏亮语音王(小) 齐心计算器 黑 C-1266 订货号:HC00727673 折扣价?***.56 销...
一元稀疏多项式计算器(安冬)_图文.doc
一元稀疏多项式计算器(安冬) - 自己编写的,分享一下,不足之处望指正。实现模拟计算器的外观
临时用电计算Excel表格(迷你实用版)_图文.xls
临时用电计算Excel表格(迷你实用版) - 施工临时用电计算 一、计算参数 施
更多相关标签: