VC版计算器(豪华界面)

一.  功能需求: 

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.    用例图:

VC版计算器(豪华界面)_第1张图片

2.    类图:

这其中包含了主要的类,还有其它不太重要的类,如:

CMyButton类:实现按钮自绘的类;

PlayBtnMusic类:播放按键音类;

CHelp类:对各种按键进行说明的类:

ddVC版计算器(豪华界面)_第2张图片

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.显示关于对话框的“帮助”菜单。

     对话框设计截图如下:

   VC版计算器(豪华界面)_第3张图片

   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;
}


 

三.  测试与实现:

VC版计算器(豪华界面)_第4张图片

四.  总结:

   通过对计算器的设计改进,使我体会到好的代码与好的构架对于软件开发的重要性,如果微软的WordExcel在设计时,没有好的架构,无法实现代码的高效的重用,那微软一定不会走到今天。正是因为其好的架构,使其能不断根据客户的需求不断改进,从而不断推出新的版本,新的版本一定是在原来的基础上进行的改进,不可能重新编写,否则代价是相当大的。

   采用三层架构的模式,使得表示层、应用层与数据层分开,这样的设计对于大型的软件的优势及作用是相当明显的。像我们编写的这种小程序,可能还无法深刻体会其好处。但我们应该具备这样的思想。

本程序的优点:实现了几乎所有的科学计算器的功能。具有较好的界面,以及对按键、鼠标的及时响应和按键音,这使得用户体验更加丰富。

本程序的缺点:括号等功能还未实现,部分测试还不尽理想,还有很多有待提高的地方。(因为加括号的话,就得用表达式求值,原来的表示层框架就得全改,因为时间有限,所以没能加上)

 转载请标明出处:http://blog.csdn.net/u012027907

 

 

 

你可能感兴趣的:(计算器,VC)