一. 功能需求:
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