一. 功能需求:
1. 能进行加、减、乘、除运算:
这时最基本的计算器功能。
2. 还能进行以下的数值计算:
函数名:ln
在数学中ln(x)是以e为底的x的对数。 e是一个常数
函数名: exp功能: 指数函数
exp就是以e为底的指数,exp(0)=1, exp(1)=e, exp(2)=e
n!代表一个数的阶乘,例如:5!就是5*4*3*2*1;
sta代表统计算法;
x^3代表x的3次方;
x^y代表x的y次方。
sin正弦,
cos余弦,
tan正切,
dms度分秒切换
Lsh左移
ln自然对数,
F-E科学计数法开关,Xor异或,
Int整数部分,
Exp允许输入用科学计数法表示的数字
1/x倒数,
log常用倒数
mod余数
Pi是圆周率,
Exp是科学计数法
exp代表以e为幂指数函数例如:exp10就是e的10次方;
ln是以e为底的对数函数例如:ln10就是以e为底10的对数;
M+是计算结果并加上已经储存的数;
M-是计算结果并用已储存的数字减去目前的结果;
MR是读取储存的数据;
MC是清除储存数据;
AC,CE归零是有一个是清除现有数据重新输入,另一个是清除全部数据结果和运算符.等。
转载请标明出处:http://blog.csdn.net/u012027907
二. 总体设计:
1. 用例图:
2. 类图:
这其中包含了主要的类,还有其它不太重要的类,如:
CMyButton类:实现按钮自绘的类;
PlayBtnMusic类:播放按键音类;
CHelp类:对各种按键进行说明的类:
3. 设计
(1)对话框窗体及各种资源的设计:
(1).要进行计算,必须要添加相应的按钮。
这其中包括能进行计算的数字按钮和操作符按钮两种按键按钮;
还有能进行数制转换和角度、弧度转换的单选按钮;以及能求反函数的复选框与组框。
(2).要能显示计算机过及过程,必须有编辑框。
(3).要能有菜单就更好了,其可以实现复制、拷贝,进制转换及显示关于对话框。
(2). 对资源进行响应的各种函数设计:
(1).对数字按钮进行响应的函数。
(2).对操作符进行响应的函数。
(3).对进制转换进行响应的函数。
(4).对弧度、角度转换进行响应的函数。
(5).存储数值的函数及求阶乘等函数。
三. 详细设计:
A.表示层:
1. 对话框窗体及各种资源的设计:
(1).按钮设计:
A. 按键按钮:
数字按钮和操作符按钮两种;
B. 单选按钮:
数制转换和角度、弧度转换的单选按钮
C. 复选框:
求反函数的复选框。
D.组框:
将相应的具有同类型的按钮分组,并显示在一个框中。
(2).编辑框:
A.进行数字显示的主编辑框。
B.存储计算结果按MS按钮时,显示M的编辑框,及按括号时,显示括号的编辑框。
(3).菜单:
A.实现复制、拷贝的“编辑”菜单。
B.进制转换及角度弧度转换选择的“查看”菜单。
C.显示关于对话框的“帮助”菜单。
对话框设计截图如下:
2. 对资源进行响应的各种函数设计:
(1).对数字按钮进行响应的函数:
由于数字等按钮有10几个,若能将其实现在一个函数(OnNumberKey())中,并用ON_COMMAND_RANGE宏实现对多个具有相同属性按钮的集体映射。便可以避免对没有个按钮单个映射的麻烦。
代码如下:
//----------------------操作数按钮响应函数---------------- void CCalculatorDlg::OnNumberKey(UINT nID) { ////播放按键音 PressBtnMusic Play; Play.PlayMusic(); /////定义局部变量 TransForm trans; CString n,pi; CString strexpshow; int inpi=0; ///若上次按键为 “=”,按数字时,重新初始化一些变量 if(OperationState == IDC_NUMBER_Equal) { number1=m_number; OperationState = 0; m_copym=m_number; m_equalvalue=m_Cnumber; number1 = m_number; m_number=0; m_Cnumber=""; } //----- switch(nID) { case IDC_NUMBER1:n="1";break; case IDC_NUMBER2:n="2";break; case IDC_NUMBER3:n="3";break; case IDC_NUMBER4:n="4";break; case IDC_NUMBER5:n="5";break; case IDC_NUMBER6:n="6";break; case IDC_NUMBER7:n="7";break; case IDC_NUMBER8:n="8";break; case IDC_NUMBER9:n="9";break; case IDC_NUMBER0:n="0";break; case IDC_NUMBER_A:n="A";break; case IDC_NUMBER_B:n="B";break; case IDC_NUMBER_C:n="C";break; case IDC_NUMBER_D:n="D";break; case IDC_NUMBER_E:n="E";break; case IDC_NUMBER_F:n="F";break; case IDC_NUMBERpoint: if(!m_PointFlag) n="."; //如果输入一个点后,就不能再输入点 else n=""; if(m_Cnumber=="") m_Cnumber="0"; //如果直接按小数点按钮,小数点前显示“0” m_PointFlag=1; break; case IDC_NUMBER_PI:inpi=1;break; default:break; } if(NumberState==1) { if(inpi==1) { number1=ExPi(); m_Cnumber.Format("%g",ExPi()); //输入pi时,对其单独响应并转换 UpdateData(FALSE); } else { if(m_flagexp==1) //当使用科学计数法时,对数字单独进行存储 { m_Cnumber=m_Cnumber+n; strexpshow=strexpshow+n; number2=atof(strexpshow); UpdateData(FALSE); } else { m_Cnumber=m_Cnumber+n; if(m_NR==10) //若选择十进制,直接使用atof()函数转换 number1=atof(m_Cnumber); else //否则,为其它进制时,都先转换为为十进制 { number1=trans.Transform_to10(m_Cnumber,m_NR); m_Cnumber=trans.Transform_to_2_8_16(number1,m_NR);} //再转换为相应的进制显示 UpdateData(FALSE); } } } else //if(NumberState==2) //数字状态为2时,与1相同 { if(inpi==1) { number2=ExPi(); m_Cnumber.Format("%g",ExPi()); UpdateData(FALSE); } else { if(m_flagexp==1) { m_Cnumber=m_Cnumber+n; strexpshow=strexpshow+n; number2=atof(strexpshow); UpdateData(FALSE);} else { m_Cnumber=m_Cnumber+n; if(m_NR==10) number2=atof(m_Cnumber); else { number2=trans.Transform_to10(m_Cnumber,m_NR); m_Cnumber=trans.Transform_to_2_8_16(number2,m_NR);} UpdateData(FALSE); } } } }
(2).对操作符进行响应的函数:
除了数字外,其余全都可视为操作符,将其设计在一个函数中,
能进行单目运算的设计一个OnOperationKey()函数,进行双目运算的设计一个Cal()函数。
大部分的单目运算但可使用math.h中相应的库函数来实现,其他一部分可通过自己设及实现。
部分实现代码如下:
//-------------操作符按钮响应函数---------------- void CCalculatorDlg::OnOperationKey(UINT nID) { /////播放按键音 PressBtnMusic Play; Play.PlayMusic(); ///////////////// TransForm trans; if(m_NR==10) //若选择十进制,直接使用atof()函数转换 m_number=atof(m_Cnumber); else //否则,为其它进制时,都先转换为为十进制 m_number=trans.Transform_to10(m_Cnumber,m_NR); ////////// m_PointFlag=0; //使用完操作符后,使点标志为初始状态,即下次输入数字时还可再用点 int i=0; CString str,a; int cout=0; //转换为科学记数法时,记录指数 CString strcout; //将cout整型转化为CString型 int flagExp=0; //pi标志置为初始状态 bool invalid = false; ///////////// switch(nID) { case IDC_NUMBER_BackSpace: int n; n=m_Cnumber.GetLength(); m_Cnumber=m_Cnumber.Left(n-1); UpdateData(FALSE); break; case IDC_NUMBER_Clear: number1=number2=m_number=0; m_Cnumber=trans.Transform_to_2_8_16(m_number,m_NR); UpdateData(FALSE); m_Cnumber=""; NumberState=1; IsButtonPress=true; break; case IDC_NUMBER_CE: //清除当前输入 if(NumberState==1) number1=m_number=0; else number2=m_number=0; m_Cnumber.Format("%g",m_number); UpdateData(FALSE); m_Cnumber=""; break; ///-------------双目运算---------------- case IDC_NUMBER_Divide:cal(OperationState); OperationState = IDC_NUMBER_Divide; m_number=0; m_Cnumber=""; NumberState=2; break; case IDC_NUMBER_Multiply:cal(OperationState); OperationState = IDC_NUMBER_Multiply; m_number=0; m_Cnumber=""; NumberState=2; break; case IDC_NUMBER_Add:cal(OperationState); OperationState = IDC_NUMBER_Add; m_number=0; m_Cnumber=""; NumberState=2; break; case IDC_NUMBER_Subtract:cal(OperationState); OperationState = IDC_NUMBER_Subtract; m_number=0; m_Cnumber=""; NumberState=2; break; case IDC_NUMBER_Mod:cal(OperationState); //取余按钮响应 OperationState = IDC_NUMBER_Mod; m_number=0; m_Cnumber=""; NumberState=2; break; case IDC_NUMBER_E_X_P:cal(OperationState); //用科学计数法输入 m_flagexp=1; OperationState = IDC_NUMBER_E_X_P; m_number=0; m_Cnumber.Format("%g",number1); m_Cnumber=m_Cnumber+"."+"e"+"+"; NumberState=2; UpdateData(FALSE); break; case IDC_NUMBER_And:cal(OperationState); //按位与按钮响应 OperationState = IDC_NUMBER_And; m_number=0; m_Cnumber=""; NumberState=2; break; case IDC_NUMBER_Or:cal(OperationState); //按位或按钮响应 OperationState = IDC_NUMBER_Or; m_number=0; m_Cnumber=""; NumberState=2; break; case IDC_NUMBER_Xor:cal(OperationState); //按位异或按钮响应 OperationState = IDC_NUMBER_Xor; m_number=0; m_Cnumber=""; NumberState=2; break; case IDC_NUMBER_X_Y: //求x的y次方 OperationState = IDC_NUMBER_X_Y; m_number=0; m_Cnumber=""; NumberState=2; break; //-------------单目运算-------------- case IDC_NUMBER_PlusMinus:m_number = sinop.GetResult(nID,m_number); if(NumberState==1) number1=m_number; else number2=m_number; m_Cnumber.Format("%g",m_number); UpdateData(FALSE); break; case IDC_NUMBER_Not: //非按钮响应 number1=m_number = sinop.GetResult(nID,number1); m_Cnumber.Format("%g",m_number); UpdateData(FALSE); m_copym=m_number; m_number=0; m_Cnumber=""; break; case IDC_NUMBER_Sqrt: number1=m_number = sinop.GetResult(nID,number1); m_Cnumber.Format("%g",m_number); UpdateData(FALSE); m_copym=m_number; m_number=0; m_Cnumber=""; break; case IDC_NUMBER_Derivative: number1=m_number = sinop.GetResult(nID,number1); m_Cnumber.Format("%g",m_number); UpdateData(FALSE); m_copym=m_number; m_number=0; m_Cnumber=""; break; case IDC_NUMBER_Sin: if(m_angle_radian==1) //若选为角度 { if(((CButton*)GetDlgItem(IDC_CHECK_Inv))->GetCheck()==FALSE) //当没有选用反函数复选框时 {number1=m_number=angle.AngleToArc(number1); m_number=sinop.GetResult(nID,number1);} else //当选用反函数复选框时 { if(!(m_number<=1&&m_number>=-1)) //判断输入是否符合要求 {m_Cnumber="函数输入无效"; invalid = true; UpdateData(FALSE); //break; } else { number1 = m_number =sinop.GetResult(IDC_NUMBER_ASin,number1); } m_Inv=false; ((CButton*)GetDlgItem(IDC_CHECK_Inv))->SetCheck(FALSE); //当用完反函数复选框时,将其置为未选状态 } } else { if(m_Inv==true) { if(!(m_number<=1&&m_number>=-1)) //判断输入是否符合要求 {m_Cnumber="函数输入无效"; invalid = true; UpdateData(FALSE); } else { number1=m_number=sinop.GetResult(IDC_NUMBER_ASin,number1);//asin(number1); } m_Inv=false; ((CButton*)GetDlgItem(IDC_CHECK_Inv))->SetCheck(FALSE); } else number1=m_number = sinop.GetResult(nID,number1);//sin(number1); } if(!invalid) { if(fabs(m_number) < 1e-6) m_Cnumber.Format("%d",m_number); else m_Cnumber.Format("%g",m_number); UpdateData(FALSE); } m_copym=m_number; m_number=0; m_Cnumber=""; m_dms=0; break; case IDC_NUMBER_Cos: //Cos与Sin类似 if(m_angle_radian==1) { if(((CButton*)GetDlgItem(IDC_CHECK_Inv))->GetCheck()==FALSE) {number1=m_number= angle.AngleToArc(number1); m_number = sinop.GetResult(nID,number1);} else { if(!(m_number<=1&&m_number>=-1)) {m_Cnumber="函数输入无效"; invalid = true; UpdateData(FALSE); //break; } else { // number1=m_number=(acos(number1)/(asin(0.5)*6)); // number1=m_number=180*(number1); number1 = sinop.GetResult(IDC_NUMBER_ACos,number1); } m_Inv=false; ((CButton*)GetDlgItem(IDC_CHECK_Inv))->SetCheck(FALSE); } } else { if(m_Inv==true) { if(!(m_number<=1&&m_number>=-1)) //判断输入是否符合要求 {m_Cnumber="函数输入无效"; invalid = true; UpdateData(FALSE); } else { number1=m_number= sinop.GetResult(IDC_NUMBER_ACos,number1); } m_Inv=false; ((CButton*)GetDlgItem(IDC_CHECK_Inv))->SetCheck(FALSE); } else number1=m_number = sinop.GetResult(nID,number1); } if(!invalid) { if(fabs(m_number) < 1e-6) m_Cnumber.Format("%d",m_number); else m_Cnumber.Format("%g",m_number); UpdateData(FALSE); } m_copym=m_number; m_number=0; m_Cnumber=""; m_dms=0; break; case IDC_NUMBER_Tan: if(m_angle_radian==1) number1=m_number= angle.AngleToArc(number1); if(m_Inv==true) {number1=m_number= sinop.GetResult(IDC_NUMBER_ATan,number1); m_Inv=false;} else number1=m_number = sinop.GetResult(nID,number1); if(fabs(m_number) < 1e-6) m_Cnumber.Format("%d",m_number); else m_Cnumber.Format("%g",m_number); UpdateData(FALSE); m_copym=m_number; m_number=0; m_Cnumber=""; m_dms=0; break; case IDC_NUMBER_Log: number1=m_number = sinop.GetResult(nID,number1); m_Cnumber.Format("%g",m_number); UpdateData(FALSE); m_copym=m_number; m_number=0; m_Cnumber=""; break; case IDC_NUMBER_In: number1=m_number = sinop.GetResult(nID,number1); m_Cnumber.Format("%g",m_number); UpdateData(FALSE); m_copym=m_number; m_number=0; m_Cnumber=""; break; case IDC_NUMBER_Sinh: number1=m_number = sinop.GetResult(nID,number1); m_Cnumber.Format("%g",m_number); UpdateData(FALSE); m_copym=m_number; m_number=0; m_Cnumber=""; break; case IDC_NUMBER_Cosh: number1=m_number = sinop.GetResult(nID,number1); m_Cnumber.Format("%g",m_number); UpdateData(FALSE); m_copym=m_number; m_number=0; m_Cnumber=""; break; case IDC_NUMBER_Tanh: number1=m_number = sinop.GetResult(nID,number1); m_Cnumber.Format("%g",m_number); UpdateData(FALSE); m_copym=m_number; m_number=0; m_Cnumber=""; break; case IDC_NUMBER_X_3: number1=m_number = sinop.GetResult(nID,number1); m_Cnumber.Format("%g",m_number); UpdateData(FALSE); m_copym=m_number; m_number=0; m_Cnumber=""; break; case IDC_NUMBER_X_2: number1=m_number = sinop.GetResult(nID,number1); m_Cnumber.Format("%g",m_number); UpdateData(FALSE); m_copym=m_number; m_number=0; m_Cnumber=""; break; case IDC_NUMBER_N: //求n的阶乘 number1=m_number = sinop.GetResult(nID,number1); m_Cnumber.Format("%g",m_number); UpdateData(FALSE); m_copym=m_number; m_number=0; m_Cnumber=""; break; case IDC_NUMBER_Exp: //求e的x次方 number1=m_number = sinop.GetResult(nID,number1); m_Cnumber.Format("%g",m_number); UpdateData(FALSE); m_copym=m_number; m_number=0; m_Cnumber=""; break; case IDC_NUMBER_Int: //取整 number1=m_number = sinop.GetResult(nID,number1); m_Cnumber.Format("%g",m_number); UpdateData(FALSE); m_copym=m_number; m_number=0; m_Cnumber=""; break; case IDC_NUMBER_E_X: //求10的x次方 number1=m_number = sinop.GetResult(nID,number1); m_Cnumber.Format("%g",m_number); UpdateData(FALSE); m_copym=m_number; m_number=0; m_Cnumber=""; break; //--------特殊运算符--------------- case IDC_NUMBER_Dms: //度分秒的转换 if(m_angle_radian==1) //当选用角度是才可用 { m_dms++; if(m_dms==1) { number1=m_dms_save=number1/180*asin(0.5)*6; number1=m_dms_save=cos(number1); } else if(m_dms==2) { number1=m_dms_save+number1/180/60*asin(0.5)*6; number1=m_dms_save=cos(number1); } else if(m_dms==3) { number1=m_dms_save+number1/180/60/60*asin(0.5)*6; number1=m_dms_save=cos(number1); m_dms=0; m_dms_save=0; } } m_copym=m_number; m_number=0; m_Cnumber=""; break; case IDC_NUMBER_F_E: //用科学计数法表示 if(m_equalflag==1) m_Cnumber=m_equalvalue; n=m_Cnumber.GetLength(); while(n!=(i+1)) { switch(m_Cnumber.GetAt(i++)) { case '0':a="0";break; case '1':a="1";break; case '2':a="2";break; case '3':a="3";break; case '4':a="4";break; case '5':a="5";break; case '6':a="6";break; case '7':a="7";break; case '8':a="8";break; } str=str+a; if(i==1) str=str+"."; } a.Format("%g",(double)(i)); m_Cnumber=str+"e+"+a; UpdateData(FALSE); m_Cnumber=""; break; //-------等于运算符------------- case IDC_NUMBER_Equal:cal(OperationState); //按位异或按钮响应 OperationState = IDC_NUMBER_Equal; m_number=0; //m_Cnumber=""; NumberState=2; m_equalflag=1; break; } } //---------计算双目运算符的结果-------------- //此函数并不进行真正的计算,实际计算调用DoubleOperation类的GetResult()函数完成 void CCalculatorDlg::cal(UINT nID) { TransForm trans; switch(OperationState) { case IDC_NUMBER_Divide: if(number2==0) //判断出书是否为“0” { m_Cnumber = "除数不能为0"; UpdateData(FALSE); } else { m_number = douop.GetResult(nID,number1,number2); //调用DoubleOperation类的GetResult()函数相应的计算完成 NumberState=1; if(m_NR==10) m_Cnumber.Format("%g",m_number); else m_Cnumber = trans.Transform_to_2_8_16(m_number,m_NR); UpdateData(FALSE);} break; case IDC_NUMBER_Multiply: m_number = douop.GetResult(nID,number1,number2); NumberState=1; if(m_NR==10) //若为十进制直接转换 m_Cnumber.Format("%g",m_number); else //否则转换为相应的进制显示 m_Cnumber=trans.Transform_to_2_8_16(m_number,m_NR); UpdateData(FALSE); break; case IDC_NUMBER_Add: m_number = douop.GetResult(nID,number1,number2); NumberState=1; if(m_NR==10) m_Cnumber.Format("%g",m_number); else m_Cnumber=trans.Transform_to_2_8_16(m_number,m_NR); UpdateData(FALSE); break; case IDC_NUMBER_Subtract: m_number = douop.GetResult(nID,number1,number2); NumberState=1; if(m_NR==10) m_Cnumber.Format("%g",m_number); else m_Cnumber=trans.Transform_to_2_8_16(m_number,m_NR); UpdateData(FALSE); break; case IDC_NUMBER_X_Y: m_number = douop.GetResult(nID,number1,number2); NumberState=1; m_Cnumber.Format("%g",m_number); UpdateData(FALSE); break; case IDC_NUMBER_Mod: m_number = douop.GetResult(nID,number1,number2); NumberState=1; m_Cnumber.Format("%g",m_number); UpdateData(FALSE); break; case IDC_NUMBER_E_X_P: m_number = douop.GetResult(nID,number1,number2); NumberState=1; m_Cnumber.Format("%g",m_number); UpdateData(FALSE); break; case IDC_NUMBER_And: m_number = douop.GetResult(nID,number1,number2); NumberState=1; m_Cnumber.Format("%g",(double)m_number); UpdateData(FALSE); break; case IDC_NUMBER_Or: m_number = douop.GetResult(nID,number1,number2); NumberState=1; m_Cnumber.Format("%g",(double)m_number); UpdateData(FALSE); break; case IDC_NUMBER_Xor: m_number = douop.GetResult(nID,number1,number2); NumberState=1; m_Cnumber.Format("%g",(double)m_number); UpdateData(FALSE); break; case IDC_NUMBER_Equal: // m_number = douop.GetResult(nID,number1,number2); NumberState=1; if(m_NR==10) //若为十进制直接转换 m_Cnumber.Format("%g",m_number); else //否则转换为相应的进制显示 m_Cnumber=trans.Transform_to_2_8_16(m_number,m_NR); UpdateData(FALSE); break; } if(OperationState != IDC_NUMBER_Equal) { number1=m_number; OperationState = 0; m_copym=m_number; m_equalvalue=m_Cnumber; number1 = m_number; m_number=0; m_Cnumber=""; } }
(3).对进制转换进行响应的函数:
为了进行进制的转换,需要对应的函数,而且转换后的数据还能进行相应的运算,所以,将任何的进制先转换为十进制,这样可以进行相应的运算,然后再将结果转换为相应的进制显示出来。
部分代码如下:
//----------------进制转换响应函数------------------------ void CCalculatorDlg::Transform(UINT nID) //进制转换 { TransForm trans; if(m_equalflag==1) //若按下等于按钮,将其值赋给m_Cnumber m_Cnumber=m_equalvalue; switch(nID) { case IDC_RADIO16: //若按下16进制按钮 //设置灰显 Setgray(nID,m_NR); ///////////////////////////////////////////////// number1=m_number=trans.Transform_to10(m_Cnumber,m_NR); //转化为10进制数 m_NR=16; m_Cnumber=trans.Transform_to_2_8_16(number1,m_NR); //转化为相应进制显示 UpdateData(FALSE); break; case IDC_RADIO10: //设置灰显 Setgray(nID,m_NR); number1=m_number=trans.Transform_to10(m_Cnumber,m_NR); m_NR=10; m_Cnumber=trans.Transform_to_2_8_16(number1,m_NR); UpdateData(FALSE); break; case IDC_RADIO8: //设置灰显 Setgray(nID,m_NR); /////////////////////////////////////////////////// number1=m_number=trans.Transform_to10(m_Cnumber,m_NR); m_NR=8; m_Cnumber=trans.Transform_to_2_8_16(number1,m_NR); UpdateData(FALSE); break; case IDC_RADIO2: Setgray(nID,m_NR); /////////////////////////////////////////////////// m_number=trans.Transform_to10(m_Cnumber,m_NR); m_NR=2; m_Cnumber=trans.Transform_to_2_8_16(m_number,m_NR); UpdateData(FALSE); break; } //m_equalvalue=""; m_equalflag=0; }
(4).对弧度、角度转换进行响应的函数:
由于math.h的sin()等函数默认为弧度计算,当计算弧度时,直接使用,相应的函数。当选择角度时,只需将输入的角度转换为相应的弧度即可。
部分代码如下:
void CCalculatorDlg::Angle_Radian(UINT nID) //弧度、角度切换响应函数 { //m_angle_radian=((CButton*)GetDlgItem(IDC_RADIO_RADIAN))->GetCheck(); switch(nID) { case IDC_RADIO_ANGLE: ((CButton*)GetDlgItem(IDC_RADIO_RADIAN))->SetCheck(FALSE); ((CButton*)GetDlgItem(IDC_RADIO_ANGLE))->SetCheck(TRUE); m_angle_radian=1; break; case IDC_RADIO_RADIAN: ((CButton*)GetDlgItem(IDC_RADIO_ANGLE))->SetCheck(FALSE); ((CButton*)GetDlgItem(IDC_RADIO_RADIAN))->SetCheck(TRUE); m_angle_radian=0; break; } }
(5).存储数值的函数及求阶乘等函数:
存储数据只需一个CString类的变量即可。
部分代码如下:
//-------------------存储数据按钮响应函数------------------------- void CCalculatorDlg::M_Savadate(UINT nID) //存储数据 { m_PointFlag=0; TransForm trans; switch(nID) { case IDC_NUMBER_Mplus: //M+:存储数据加上当前数据 m_number=trans.Transform_to10(m_Cnumber,m_NR); m_number = msave.SaveData(nID,m_number); m_Cnumber=trans.Transform_to_2_8_16(m_number,m_NR); UpdateData(FALSE); break; case IDC_NUMBER_Mminus: //M-:存储数据减去当前数据 m_number=trans.Transform_to10(m_Cnumber,m_NR); m_number = msave.SaveData(nID,m_number); m_Cnumber=trans.Transform_to_2_8_16(m_number,m_NR); UpdateData(FALSE); break; case IDC_NUMBER_MS: //MS:存储数据 m_number=trans.Transform_to10(m_Cnumber,m_NR); msave.SaveData(nID,m_number); m_M="M"; //显示M的编辑框显示M标志 UpdateData(FALSE); m_Cnumber=""; break; case IDC_NUMBER_MR: //MR:显示存储的数据 m_number = msave.SaveData(nID,m_number);; m_Cnumber=trans.Transform_to_2_8_16(m_number,m_NR); UpdateData(FALSE); break; case IDC_NUMBER_MC: //MC:清空存储的数据 msave.SaveData(nID,m_number); m_M=""; //显示M的编辑框清除M标志 UpdateData(FALSE); break; } }
B.业务逻辑层
1.单目运算
double SingleOperation::GetResult(UINT nID,double Num1) { double Result; switch(nID) { case IDC_NUMBER_PlusMinus: Result = -Num1; break; case IDC_NUMBER_Not: Result = ~(int)Num1; break; case IDC_NUMBER_Sqrt: Result = sqrt(Num1); break; case IDC_NUMBER_Derivative: Result = (double)1/Num1; break; case IDC_NUMBER_Sin: Result = sin(Num1); break; case IDC_NUMBER_Cos: Result = cos(Num1); break; case IDC_NUMBER_Tan: Result = tan(Num1); break; case IDC_NUMBER_ASin: Result = asin(Num1); break; case IDC_NUMBER_ACos: Result = acos(Num1); break; case IDC_NUMBER_ATan: Result = atan(Num1); break; case IDC_NUMBER_Log: Result = log10(Num1); break; case IDC_NUMBER_In: Result = log(Num1); break; case IDC_NUMBER_Sinh: Result = sinh(Num1); break; case IDC_NUMBER_Cosh: Result = cosh(Num1); break; case IDC_NUMBER_Tanh: Result = tanh(Num1); break; case IDC_NUMBER_X_3: Result = (Num1*Num1*Num1); break; case IDC_NUMBER_X_2: Result = (Num1*Num1); break; case IDC_NUMBER_N: Result = (double)Fac((int)Num1); break; case IDC_NUMBER_Exp: Result = exp(Num1); break; case IDC_NUMBER_Int: Result = (int)(Num1); break; case IDC_NUMBER_E_X: Result = pow(10,Num1); break; } return Result; }
2.双目运算
double DoubleOperation::GetResult(UINT nID,double Num1,double Num2) { switch(nID) { case IDC_NUMBER_Divide: Result = Num1 / Num2; break; case IDC_NUMBER_Multiply: Result = Num1 * Num2; break; case IDC_NUMBER_Add: Result = Num1 + Num2; break; case IDC_NUMBER_Subtract: Result = Num1 - Num2; break; case IDC_NUMBER_Mod: Result = fmod(Num1,Num2); break; case IDC_NUMBER_And: Result = (int)Num1 & (int)Num2; break; case IDC_NUMBER_Xor: Result = (int)Num1 ^ (int)Num2; break; case IDC_NUMBER_Or: Result = (int)Num1 | (int)Num2; break; case IDC_NUMBER_X_Y: Result = pow(Num1,Num2); break; case IDC_NUMBER_E_X_P: Result = (double)Num1*pow(10,Num2); break; default:break; } return Result; }
3.进制转换
//****************其他进制转换为10进制******************* double TransForm::Transform_to10(CString m_Cnumber,int m_NR) { int m_copym; int sum=0; int i=0,mod,n; if(m_NR==2) //若原来是2进制数,转化为10进制 { m_copym=(int)atof(m_Cnumber); n=m_Cnumber.GetLength(); while(n--) { mod=m_copym%10; m_copym=m_copym/10; sum=sum+mod*(int)pow(m_NR,i++); } } else if(m_NR==8) //若原来是8进制数,转化为10进制 { m_copym=(int)atof(m_Cnumber); n=m_Cnumber.GetLength(); while(n--) { mod=m_copym%10; m_copym=m_copym/10; sum=sum+mod*(int)pow(m_NR,i++); } } else if(m_NR==16) //若原来是16进制数,转化为10进制 { int a; i=0; n=m_Cnumber.GetLength(); while(n) { switch(m_Cnumber.GetAt(--n)) { case '0':a=0;break; case '1':a=1;break; case '2':a=2;break; case '3':a=3;break; case '4':a=4;break; case '5':a=5;break; case '6':a=6;break; case '7':a=7;break; case '8':a=8;break; case '9':a=9;break; case 'A':a=10;break; case 'B':a=11;break; case 'C':a=12;break; case 'D':a=13;break; case 'E':a=14;break; case 'F':a=15;break; } sum=sum+a*(int)pow(m_NR,i++); } } else sum=(int)atof(m_Cnumber); m_record = sum; return (double)sum; } //*************10进制转换为其他进制*********************** CString TransForm::Transform_to_2_8_16(double m,int m_NR) { SeqStack S; int x; CString Str,n; Init_Stack(&S); if(m_NR==2) { while((int)m) {Push_Stack(&S,(int)m%2); m=m/2;} m=0; while(!Empty_Stack(&S)) {Pop_Stack(&S,&x); switch(x) { case 1:n="1";break; case 0:n="0";break; } Str=Str+n; } } else if(m_NR==8) { while((int)m) {Push_Stack(&S,(int)m%8); m=m/8;} m=0; while(!Empty_Stack(&S)) {Pop_Stack(&S,&x); m=m*10+x;} Str.Format("%g",(double)m); } else if(m_NR==16) { while((int)m) {Push_Stack(&S,(int)m%16); m=m/16;} m=0; while(!Empty_Stack(&S)) {Pop_Stack(&S,&x); switch(x) { case 1:n="1";break; case 2:n="2";break; case 3:n="3";break; case 4:n="4";break; case 5:n="5";break; case 6:n="6";break; case 7:n="7";break; case 8:n="8";break; case 9:n="9";break; case 0:n="0";break; case 10:n="A";break; case 11:n="B";break; case 12:n="C";break; case 13:n="D";break; case 14:n="E";break; case 15:n="F";break; } Str=Str+n; } } else Str.Format("%g",m); return Str; }
4.角度转弧度
double Angle_Arc::AngleToArc(double angle) { double Pi = asin(0.5)*6; // double Pi = 3.1415926; Arc=angle/180*Pi; return Arc; }
5.存储数据
double M_SaveData::SaveData(UINT nID,double m_number) { double m = 0; switch(nID) { case IDC_NUMBER_Mplus: //M+:存储数据加上当前数据 return m_savedata+m_number; break; case IDC_NUMBER_Mminus: //M-:存储数据减去当前数据 return m_savedata-m_number; break; case IDC_NUMBER_MS: //MS:存储数据 m_savedata = m_number; break; case IDC_NUMBER_MR: //MR:显示存储的数据 return m_savedata; break; case IDC_NUMBER_MC: //MC:清空存储的数据 m_savedata = 0; break; } return m; }
三. 测试与实现:
四. 总结:
通过对计算器的设计改进,使我体会到好的代码与好的构架对于软件开发的重要性,如果微软的Word或Excel在设计时,没有好的架构,无法实现代码的高效的重用,那微软一定不会走到今天。正是因为其好的架构,使其能不断根据客户的需求不断改进,从而不断推出新的版本,新的版本一定是在原来的基础上进行的改进,不可能重新编写,否则代价是相当大的。
采用三层架构的模式,使得表示层、应用层与数据层分开,这样的设计对于大型的软件的优势及作用是相当明显的。像我们编写的这种小程序,可能还无法深刻体会其好处。但我们应该具备这样的思想。
本程序的优点:实现了几乎所有的科学计算器的功能。具有较好的界面,以及对按键、鼠标的及时响应和按键音,这使得用户体验更加丰富。
本程序的缺点:括号等功能还未实现,部分测试还不尽理想,还有很多有待提高的地方。(因为加括号的话,就得用表达式求值,原来的表示层框架就得全改,因为时间有限,所以没能加上)
转载请标明出处:http://blog.csdn.net/u012027907