信息科学与技术学院《程序设计基础》课程设计报告题目名称:60.编写一个能实现简单功能的计算器学生姓名:李海东学生学号:2011508154 专业班级:电子信息工程(1)班指导教师:高攀11 课程设计的题目编写一个能实现简单功能的计算器2 题目要求1. 有一个计算器图形。
2. 能实现加、减、乘、除及乘方的运算。
3. 当输入题目时,屏幕上要在指定位置上显示出相应的题目内容,且相应的数字键要改变颜色例如:输入数字1 时,在计算器图形上的1键变为红色。
4. 屏幕、图形颜色、形状自定3 总体设计3.1 总体框架图1 系统框架开始结束键入第一个按钮键入第二个按钮显 示 结 果加法减法乘法除法乘方清零3.2 系统功能说明在VC++6.0中绘制计算器界面,各控件的设置对0~9控件设定相应的ID和其他属性:图2 “1”控件设置对“+、-、*、\”控件设定相应的ID和其他属性:图2 “+”控件设置对其它控件设定相应的ID和其他属性:图3 其它控件设置12主要使用到Layout 菜单中的Align 功能对各个按钮进行对其,使界面更加整洁。
拖出的控件有上面的一个Edit 控件用于显示数字,Button 控件用于处理鼠标的消息。
4 程序详细设计4.1系统主调模块图5 程序流程图实现文件.cpp显示计算器界面开始执行工程全局对象资源文件.rc 模块定义文件.def头文件.h执行_twinmain() Afxmain()创建窗口实现窗口类注册Set window V oid clc::onpaint() V oid cal::onCE()点击鼠标发出消息V oid clce::onmouse()等待消息处理V oid clc::onMum0() V oid clc::onAdd() 文本框中显示结果程序运行结4.2各模块详细设计4.2.1 建立的变量,控件的命名,对应的消息处理函数对应表ID CAPTION Message HandlerIDD_CALC_DIALOG 简易计算器N/AIDC_NUM0 0 OnNum0IDC_NUM1 1 OnNum1IDC_NUM2 2 OnNum2IDC_NUM3 3 OnNum3IDC_NUM4 4 OnNum4IDC_NUM5 5 OnNum5IDC_NUM6 6 OnNum6IDC_NUM7 7 OnNum7IDC_NUM8 8 OnNum8IDC_NUM9 9 OnNum9IDC_NEG +/- OnNegIDC_PT .OnPtIDC_DIV / OnDivIDC_MUL * OnMulIDC_MIN - OnMinIDC_ADD + OnAddIDC_BACKSPACE BACK OnBackspaceIDC_CE CE OnCeIDC_CLEAR C OnClearIDC_EQU = OnEquIDC_DIS N/A N/AOnCal(double num)变量定义:double poz; //保存小数点的位置,初始化为1,表示poz-1个小数点。
double m_Dis; //Edit控件上需要显示的数字BOOL point_flag; //小数点表示位,判定是否是小数,是小数为1,不是小数为0。
double numfirst; //保存计算过程中的前一个数字,double numsecond;//保存计算过程中的第二个数字char op;//记录当前的计算符号,可以为’+’,’-’,’*’,’/’,’=’,’c’,’n’变量初始化:poz=1;m_Dis = 0.0;numfirst=0;numsecond=0;op=0;344.4.2 设计思路a)首先考虑对所有按键分为两类,数字类和符号类,0,1,2,3,4,5,6,7,8,9为数字类,+,-,*,/,=为符号类。
数字在计算的过程中最多需要保存两个,所以定义了两个double型变量numfirst和numsecond来进行存储。
符号需要一个char op来存储。
b)然后考虑在计算的过程中,numfirst和numsecond的存储状态有三种,一种是numfirst==0 && numsecond==0 也就是程序刚开始运行还没有开始录入数字的状态。
二种是numfirst!=0 && numsecond==0 也就是第一个数字已经录入,符号也已经录入时候把m_Dis的值直接赋值给numfirst,第三种是numfirst!=0&&numsecond!=0,表示可以通过op来把两数合并为一个数。
c)考虑到该计算器支持连续的计算,比如3.33+1.33*88/96= ?。
所以必须在点符号Button也要计算出之前的结果,通过判断op,来计算,把两个数字合并为一个数字,方便下一次运算,功能近似于点=,所以把=也划分到符号类。
d)因为数字全部使用的是double,键入的数字必须通过一定的处理达到累加的效果,加上小数和整数的处理差异性大,所以分别用point_flag来判断,分别出来小数和整数。
4.2.3 成员函数及其释义因为对OnNum0()到OnNum9()的处理函数差异仅在一个数字上,可以通过调用一个共同的函数OnCal(double num)来简化源代码长度,增加模块性。
void CCalcDlg::OnCal(double num){ //分三种状态来处理if(numfirst!=0 && numsecond!=0){if(point_flag==TRUE) //判定为小数{poz*=0.1; //小数进位m_Dis=m_Dis+poz*num;//递增UpdateData(false); //把结果从内存传递到屏幕}else{m_Dis=m_Dis*10+num;UpdateData(false);}}if(numfirst!=0 && numsecond==0){if(point_flag==TRUE){poz*=0.1;m_Dis=m_Dis+poz*num;UpdateData(false);}else//判定为整数{m_Dis=m_Dis*10+num;//递增UpdateData(false);}}if(numfirst==0 && numsecond==0){if(point_flag==TRUE){poz*=0.1;m_Dis=m_Dis+poz*num;UpdateData(false);}else{m_Dis=m_Dis*10+num;UpdateData(false);}}}4.2.4 以OnAdd()为例子讲解符号的处理函数,函数的功能是先判定之前按下字符时op的值,更具op的值来进行相应的运算。
void CCalcDlg::OnAdd(){ //根据numfirst和numsecond和op的值分为5种状态。
if(numfirst!=0 && numsecond==0&&op=='+'){numsecond=m_Dis;numfirst=numfirst+numsecond; //之前按的是加把两个数赋值到前一个数m_Dis=numfirst;//赋值给屏幕numsecond=0; //从新赋值为0,清空,不影响下一次判断UpdateData(FALSE);m_Dis=0; //屏幕的值同时清空}if(numfirst!=0 && numsecond==0&&op=='-'){numsecond=m_Dis;numfirst=numfirst-numsecond;m_Dis=numfirst;numsecond=0;UpdateData(FALSE);m_Dis=0;}if(numfirst!=0 && numsecond==0&&op=='*'){numsecond=m_Dis;numfirst=numfirst*numsecond;m_Dis=numfirst;numsecond=0;UpdateData(FALSE);m_Dis=0;}if(numfirst!=0 && numsecond==0&&op=='/'){12numsecond=m_Dis;numfirst=numfirst/numsecond;m_Dis=numfirst;numsecond=0;UpdateData(FALSE);m_Dis=0;}if(numfirst==0 && numsecond==0){ //该状态为程序启动还没有开始录入输入的状态numfirst=m_Dis; //屏幕的值赋值到numfirstUpdateData(FALSE);m_Dis=0;}op='+'; //最后记录最后一个操作是+poz=1;//小数点位置归位point_flag=FALSE;//默认小数点标志为整数,也就是0,也就是FALSE}“+/-“按钮的处理函数void CCalcDlg::OnNeg(){m_Dis=-m_Dis;//换个符号,其他都一样UpdateData(FALSE);poz=1;point_flag=FALSE;}‘.’按钮的处理函数void CCalcDlg::OnPt(){point_flag=TRUE; //把标志位改为“小数点”状态}“Backspace”按钮的处理void CCalcDlg::OnBackspace(){//主要通过_gcvt()和strtod()函数进行字符串和浮点数之间的转换char buffer[30]; //定义个装字符的数组_gcvt(m_Dis,sizeof(m_Dis),buffer); //把m_Dis存的数字转换为stringfor(int i=0;i<30;i++){if(buffer[i]=='.'&& buffer[i+1]==0)//判断是否为整数{point_flag=FALSE; //标志位设置为“整数位”break;}}if(point_flag==TRUE) //如果是小数{for(int j=0;j<30;j++){if(buffer[j]==0){buffer[j-1]=0; //把’\0’之前的字符赋值为’\0’,就相当于剪掉最后一位break;}}}else//如果是整数{buffer[i-1]=0; //剪掉’.’之前那位}m_Dis=strtod(buffer,NULL);//再用strtod弄成浮点数UpdateData(FALSE);poz=1;}‘CE’按钮处理函数void CCalcDlg::OnCe(){if(numfirst!=0 && numsecond==0)//CE只能修改第二个数字{m_Dis=0; //把屏幕的值赋值为0UpdateData(FALSE);//并显示出来}}‘C’按钮处理函数void CCalcDlg::OnClear(){op=NULL; //清空符号numfirst=0;//清空第一个数字numsecond=0;//清空第二个数字point_flag=FALSE;//改为默认整数位poz=1;//小数点归位m_Dis=0;UpdateData(FALSE); //屏幕显示归0}键盘响应:void CCalcDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags){switch(nChar){case VK_NUMPAD0:OnNum0();break;case VK_NUMPAD1:OnNum1();break;case VK_NUMPAD2:OnNum2();break;case VK_NUMPAD3:OnNum3();break;case VK_NUMPAD4:OnNum4();break;case VK_NUMPAD5:OnNum5();break;case VK_NUMPAD6:OnNum6();break;case VK_NUMPAD7:OnNum7();break;case VK_NUMPAD8:34OnNum8();break;case VK_NUMPAD9:OnNum9();break;case VK_ADD:OnAdd();break;case VK_SUBTRACT:OnMin();break;case VK_MULTIPLY:OnMul();break;case VK_DIVIDE:OnDiv();break;case VK_BACK:OnBackspace();break;case VK_DECIMAL:OnPt();break;case VK_DELETE:OnBackspace();break;case VK_RETURN:OnEqu();break;}CDialog::OnKeyDown(nChar, nRepCnt, nFlags);}BOOL CCalcDlg::PreTranslateMessage(MSG* pMsg){SendMessage(pMsg->message,pMsg->wParam,pMsg->lParam);return CDialog::PreTranslateMessage(pMsg);}5 程序运行结果6 课程设计总结通过这次课程设计,我又收获到很多,平时的在做作业时,因为题形与结构都是很简单的,并且每一章的内容都是有相应的例题可以参考,所以在做题时没有遇到过很麻烦的问题,而这次不同了,一个课题拿到手时,给我的感觉是无从下手,而且要求很多,使得题目要求更大了。