简单计算器一、基本功能描述二进制、八进制、十进制及十六进制数的加、减、乘、除、乘方、取模等简单计算科学计算函数,包括(反)正弦、(反)余弦、(反)正切、(反)余切、开方、指数等函数运行以角度、弧度两种方式实现上述部分函数具备历史计算的记忆功能对不正确的表达式能指出其错误原因二、流程图输入数据子函数图1 输入数据子函数流程图图2三、设计步骤打开Microsoft Visual C++ 6.0,在文件中点击新建,在弹出框内选择MFC AppWizard[exe]工程,输入工程名Calculter及其所在位置,点击确定,如图3所示。
图3 新建MFC AppWizard[exe]工程将弹出MFC AppWizard-step 1对话框,选择基本对话框,点击完成,如图4所示。
图4 基本对话框这样,MFC AppWizard就建立了一个基于对话窗口的程序框架,如图5所示。
图5 新建的对话框四、界面设计1、创建控件在图5所示的Resoure View选项卡中打开Dialog资源组,双击IDD_CALCULATOR_DIALOG,在右边的窗口中显示出待编辑的对话框。
开始摆放控件,包括编辑框和按钮的创建。
按钮的创建1)在图5中Controls的“编辑框”按钮上单击鼠标左键,在对话框编辑窗口上合适的位置按下鼠标左键并拖动鼠标画出一个大小合适的编辑框。
在编辑框上单击鼠标右键,在弹出的快捷莱单中选择属性选项,此时弹出Edit属性对话框,如图6所示,在该对话框中输入ID属性。
图6 Edit属性对话框2)在图3中Controls的“Button”按钮上单击鼠标左键,在对话框上的合适的位置上按下鼠标左键并拖动鼠标画出一个大小合适的下压式按钮。
在按钮上单击鼠标右键,在弹出的快捷菜单中选择属性选项,此时也弹出Push Button属性对话框,如图7所示,在该对话框中输入控件的ID值和标题属性。
图7 Push Button属性按照上面的操作过程编辑其他按钮和编辑框等对象的属性。
表1 各按钮和编辑框等对象的属性完成后界面如图8所示。
图8 计算器界面五、计算器源程序代码// Calculation.cpp: implementation of the CCalculation class.//////////////////////////////////////////////////////////////////////#include "stdafx.h"#include "Calculator.h"#include "Calculation.h"#include "math.h"#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endif#define FUNCNUM 15 //函数个数#define CONSTNUM 11 //常数个数#define PI 3.14159//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////CCalculation::CCalculation(){//初始化函数和常数m_bDegree=0;m_nOutputFlag=0;opt[0]="e^";opt[1]="ch";opt[2]="sqr";opt[3]="sh";opt[5]="cos";opt[6]="sin";opt[7]="tan";opt[8]="ln";opt[9]="abs";opt[10]="at";opt[11]="as";opt[12]="ac";opt[13]="th";opt[14]="cot";opt2[0]='^';opt2[1]='/';opt2[2]='*';opt2[3]='%';opt2[4]='+';opt2[5]='-';m_strConValue[1]="9.80665"; m_strConName[1]="GG";m_strConValue[2]="(8.988*10^9)"; m_strConName[2]="EF";m_strConValue[3]="0.02241383"; m_strConName[3]="VM";m_strConValue[4]="(1.380662*10^(-23))"; m_strConName[4]="BC";m_strConValue[5]="8.3144"; m_strConName[5]="MG";m_strConValue[6]="(6.6720*10^(-11))"; m_strConName[6]="GR";m_strConValue[7]="(6.022045*10^23)"; m_strConName[7]="NA";}CCalculation::~CCalculation(){}bool CCalculation::IsDigital(CString str){while(str.GetAt(0)=='-') str.Delete(0);for(int i=0;i<FUNCNUM;i++) if(str.Find(opt[i])!=-1) return 0;for(i=0;i<6;i++) if(str.Find(opt2[i])!=-1) return 0;return 1;}CString CCalculation::NtoS(double d){int decimal, sign;char *buffer;buffer = _ecvt( d, 16, &decimal, &sign );CString str=buffer;if(decimal>=0 && decimal<=16) str.Insert(decimal,".");else if(decimal>16){for(int i=str.GetLength();i<decimal;i++) str+="0";else{for(int i=0;i<-decimal;i++) str.Insert(0,"0");str.Insert(0,".");}if(sign==1) str.Insert(0,"-");return str;}double CCalculation::StoN(CString str){char *stopstring;double x;x = strtod( str.GetBuffer(0), &stopstring );m_strTmp=stopstring;return x;}CString CCalculation::TwoE(CString strExp){double x2,y,x1=StoN(strExp);strExp=m_strTmp;char op=strExp.GetAt(0);strExp.Delete(0);x2=StoN(strExp);if(m_strTmp!="") return "ERROR_"+m_strTmp+"未知符号_";if(op=='+') {y=x1+x2;}else if(op=='*') {y=x1*x2;}else if(op=='-') {y=x1-x2;}else if(op=='^') {y=pow(x1,x2);}else if(op=='/') {y=x1/x2;}else if(op=='%') {y=fmod(x1,x2);}else return "ERROR_"+m_strTmp+"未知运算符_";return NtoS(y);}CString CCalculation::SingleE(CString op,double dx){if(op=="ln"){return NtoS(log(dx));}else if(op=="log"){return NtoS(log10(dx));}return NtoS(sqrt(dx));}else if(op=="e^"){return NtoS(exp(dx));}else if(op=="abs"){return NtoS(fabs(dx));}else if(op=="ac"){return NtoS(acos(dx)); }else if(op=="as"){return NtoS(asin(dx));}else if(op=="at"){return NtoS(atan(dx));}if(m_bDegree) dx=dx*PI/180; if(op=="tan"){return NtoS(tan(dx));}else if(op=="sin"){return NtoS(sin(dx));}else if(op=="cos"){return NtoS(cos(dx));}else if(op=="cot"){return NtoS(1/tan(dx)); }else if(op=="sh"){return NtoS(sinh(dx));}return NtoS(cosh(dx));}else if(op=="th"){return NtoS(sinh(dx)/cosh(dx));}else if(op=="exp"){return NtoS(pow(10,dx));}return "ERROR"+op+"_未知函数_";}int CCalculation::LocateLBra(CString strExp){int len=strExp.GetLength();int pos=-1;for(int i=0;i<len;i++){if(pos>=0 && strExp.GetAt(i)==')') break;if(strExp.GetAt(i)=='('){pos=i;}}return pos;}void CCalculation::DelBracket(CString *strExp){int pos=LocateLBra(*strExp);int i,len=strExp->GetLength();if(pos==-1) {*strExp="ERROR_无效表达式_";return;}for(i=pos;i<len;i++) if(strExp->GetAt(i)==')') break;CString str;str=strExp->Mid(pos+1,i-pos-1);MultiE(&str);strExp->Delete(pos,i-pos+1);strExp->Insert(pos,str);}void CCalculation::MultiE(CString *strExp){if(strExp->IsEmpty()) *strExp="ERROR_函数表达式为空_";if(IsDigital(*strExp)) {return;}while(1)/*处理所有的一元运算*/for(int i=0;i<FUNCNUM;i++){int pos=strExp->Find(opt[i]);if(pos!=-1){CString str=strExp->Right(strExp->GetLength()-pos-opt[i].GetLength());double dx=StoN(str);if(m_strTmp==str) {*strExp="ERROR"+str+"_无法识别的函数_";return;}strExp->Delete(pos,strExp->GetLength()-pos);*strExp+=SingleE(opt[i],dx)+m_strTmp;MinusMinus(strExp);if(pos>=1){char ch=strExp->GetAt(pos-1);if(ch>=48 && ch<=57){*strExp="ERROR_缺少二元运算符_";return;}}break;}}if(i==FUNCNUM) break;}//按运算符优先级处理二元运算int pos=-1;while(1){pos=strExp->Find('^');if(pos==-1) break;else Calcu(strExp,pos);}while(1){pos=strExp->Find('/');if(pos==-1) break;else Calcu(strExp,pos);}while(1){pos=strExp->Find('*');if(pos==-1) break;else Calcu(strExp,pos);}while(1){if(pos==-1) break;else Calcu(strExp,pos);}pos=0;if(strExp->GetAt(0)=='-' ||strExp->GetAt(0)=='+') strExp->Insert(0,"0"); while(1){int tmpos=strExp->Right(strExp->GetLength()-pos).Find('-');if(tmpos==-1) break;else pos+=tmpos;if(pos==0 && strExp->GetAt(pos+1)=='-' || pos>0){if(strExp->GetAt(pos+1)=='+'){strExp->Delete(pos+1);pos=0;continue;}/*********处理连减(如:----1)的情况***********/int nCount=0;while(1){if(++pos>0){if(strExp->GetAt(pos)!='-') break;else nCount++;}else break;}if(nCount>0){strExp->Delete(pos-nCount-1,nCount+1);if(nCount%2==0) strExp->Insert(pos-nCount-1,"-");else if(pos-nCount-1>0) strExp->Insert(pos-nCount-1,"+");pos=0;continue;}else pos--;/***********************************************/if(pos>0 && strExp->GetAt(pos-1)=='+'){pos++;continue;}Calcu(strExp,pos);}else pos++;}pos=0;while(1){pos=strExp->Find('+');// int tmpos=strExp->Right(strExp->GetLength()-pos).Find('+');if(pos==-1) break;// else pos+=tmpos;if(pos==0 && strExp->GetAt(pos+1)=='+' || pos>0){/*********处理连加(如:++++1)的情况***********/int nCount=0;while(1){if(++pos>0){if(strExp->GetAt(pos)!='+') break;else nCount++;}else break;}if(nCount>0){strExp->Delete(pos-nCount-1,nCount+1);strExp->Insert(pos-nCount-1,"+");pos=0;continue;}else pos--;/***********************************************/Calcu(strExp,pos);}else pos++;}}void CCalculation::Calcu(CString *strExp,int pos){char ch;for(int j=pos-1;j>=0;j--){ch=strExp->GetAt(j);if(ch=='+' ||ch=='-' ||ch=='*'||ch=='/' ||ch=='%' ||ch=='^' ){if(j==0 && ch!='-') {*strExp="ERROR_缺少参数_";return;}if(j==0 && ch=='-') j=-1;//防止把负号误判为减号else if(j>0 && ch=='-' && !IsDigital(strExp->Mid(j-1,1))) j--;break;}}for(int k=pos+1;k<strExp->GetLength();k++){ch=strExp->GetAt(k);if(ch=='+' ||ch=='-' ||ch=='*'||ch=='/' ||ch=='%' ||ch=='^' ){if(ch=='-' && k>pos+1) break;if(ch=='-' && k>0 && IsDigital(strExp->Mid(k+1,1)) ) k++;else break;}}CString strExp2=strExp->Mid(j+1,k-j-1);*strExp=strExp->Left(j+1)+TwoE(strExp2)+strExp->Right(strExp->GetLength()-k);if(strExp->Find("#IN")!=-1) {*strExp="ERROR_结果有溢出或值域越界_";return;} if(!SynRes(strExp)) {*strExp="ERROR_缺少运算符_";return;}MinusMinus(strExp);}CString CCalculation::MainPro(CString strExp){if(strExp.IsEmpty()) return "表达式不能为空";Macro(&strExp);strExp.MakeLower(); //表达式全部小写/**********给表达式加上保护括号************/strExp.Insert(0,"(");strExp+=")";/******************************************/int pos=strExp.Find(" ");int n=BraCheck(strExp);CString str;str.Format("%d",abs(n));if(n==1) strExp+=")";else if(n==-1) strExp.Insert(0,"(");else if(n>0) return "缺少"+str+"个右括号";else if(n<0) return "缺少"+str+"个左括号";while(pos!=-1) //去掉表达式中的空格符{strExp.Delete(pos);pos=strExp.Find(" ");}Oct2Dec(&strExp); //将表达式中的八进制数转换成十进制Hex2Dec(&strExp); //将表达式中的十六进制数转换成十进制Bin2Dec(&strExp); //将表达式中的二进制数转换成十进制while(!IsDigital(strExp)){DelBracket(&strExp);if(!SynRes(&strExp)) return strExp;}if(!SynRes(&strExp)) return strExp;else return ModiResult(strExp);}void CCalculation::Macro(CString *strExp){int pos;for(int i=0;i<CONSTNUM;i++){pos=strExp->Find(m_strConName[i]);while(pos!=-1){strExp->Delete(pos,m_strConName[i].GetLength());strExp->Insert(pos,m_strConValue[i]);if(pos>=1){char ch=strExp->GetAt(pos-1);if(ch>=48 && ch<=57 || ch==41){*strExp="缺少二元运算符";return;}}pos=strExp->Find(m_strConName[i]);}}}CString CCalculation::ModiResult(CString strRes){if(strRes.Find("#IN")!=-1) return "结果有溢出或值域越界";/*****************去掉保护括号**********************/if(strRes.GetAt(0)=='(') strRes.Delete(0);if(strRes.GetAt(strRes.GetLength()-1)==')') strRes.Delete(strRes.GetLength()-1);/***************************************************/int pos=strRes.Find(".");CString str="";if(pos!=-1){if(pos==0) strRes="0"+strRes;else if(strRes.GetAt(0)=='-' && strRes.GetAt(1)=='.') strRes.Insert(1,"0");}if(pos>16){strRes.Delete(pos);strRes.Insert(1,".");str.Format("%d",pos-1);str=" E"+str;}pos=strRes.Find(".");if(pos==0 || pos==1 && strRes.GetAt(0)=='0'){for(int i=pos+1;i<strRes.GetLength();i++){if(strRes.GetAt(i)!='0') break;}if(i>4){str.Format(" E-%d",i-2);strRes.Delete(pos,i-1);strRes.Insert(1,".");}}strRes=strRes.Left(pos+16)+str;//截取小数点后16位return strRes;}bool CCalculation::SynRes(CString *strExp){int pos=strExp->Find("ERROR");if(pos!=-1){pos=strExp->ReverseFind('_');strExp->Delete(pos,strExp->GetLength()-pos);pos=strExp->ReverseFind('_');strExp->Delete(0,pos+1);return 0;}return 1;}void CCalculation::MinusMinus(CString *strExp){int pos=strExp->Find("--");if(pos!=-1){strExp->Delete(pos,2);strExp->Insert(pos,"+");if(strExp->GetAt(0)=='+') strExp->Delete(0);}}int CCalculation::BraCheck(CString str){int lb=0,rb=0,len=str.GetLength();for(int i=0;i<len;i++){if(str.GetAt(i)=='(') lb++;else if(str.GetAt(i)==')') rb++;}return lb-rb;}void CCalculation::Oct2Dec(CString *strExp){int len,i,index,pos=strExp->Find("xo");CString strTmp,strDF;char ch;double dx;while(pos!=-1){dx=0;strTmp="";strDF="";strExp->Delete(pos,2);for(i=pos-1;i>=0;i--){ch=strExp->GetAt(i);if(ch==56 || ch==57 || ch>=97 && ch<=102){*strExp="ERROR_八进制数越界_";return;}if(ch>=48 && ch<=55 ||ch==46){strTmp.Insert(0,strExp->Mid(i,1));strExp->Delete(i);}else break;}if(i==pos-1) {*strExp="ERROR_缺少二元运算符_";return;}index=i;pos=strTmp.Find(".");if(pos!=-1){strDF=strTmp.Right(strTmp.GetLength()-pos-1);strTmp.Delete(pos,strTmp.GetLength()-pos);}strTmp.MakeReverse();len=strTmp.GetLength();for(i=0;i<len;i++){ch=strTmp.GetAt(i);dx+=(ch-48)*pow(8,i);}len=strDF.GetLength();for(i=0;i<len;i++){ch=strDF.GetAt(i);dx+=(ch-48)*pow(8,-i-1);}strTmp=NtoS(dx);strExp->Insert(index+1,strTmp);pos=strExp->Find("xo");}}void CCalculation::Hex2Dec(CString *strExp){int len,i,index,pos=strExp->Find("xh");CString strTmp,strDF;char ch;double dx;while(pos!=-1){dx=0;strTmp="";strDF="";strExp->Delete(pos,2);for(i=pos-1;i>=0;i--){ch=strExp->GetAt(i);if(ch>=48 && ch<=57 || ch>=97 && ch<=102 ||ch==46){strTmp.Insert(0,strExp->Mid(i,1));strExp->Delete(i);}else break;}if(i==pos-1) {*strExp="ERROR_缺少二元运算符_";return;}index=i;pos=0;for(i=0;i<strTmp.GetLength();i++){if(strTmp.GetAt(i)=='.') pos++;if(pos>1) {*strExp="ERROR_缺少二元运算符_";return;} }pos=strTmp.Find(".");if(pos!=-1){strDF=strTmp.Right(strTmp.GetLength()-pos-1);strTmp.Delete(pos,strTmp.GetLength()-pos);}strTmp.MakeReverse();len=strTmp.GetLength();for(i=0;i<len;i++){ch=strTmp.GetAt(i);if(ch>=48 && ch<=57)//该数在0~9之间{dx+=(ch-48)*pow(16,i);}else if(ch>=97 && ch<=102)//该数在a~f之间{dx+=(ch-87)*pow(16,i);}}len=strDF.GetLength();for(i=0;i<len;i++){ch=strDF.GetAt(i);if(ch>=48 && ch<=57)//该数在0~9之间{dx+=(ch-48)*pow(16,-i-1);}else if(ch>=97 && ch<=102)//该数在a~f之间{dx+=(ch-87)*pow(16,-i-1);}}strTmp=NtoS(dx);strExp->Insert(index+1,strTmp);pos=strExp->Find("xh");}}void CCalculation::Bin2Dec(CString *strExp){int len,i,index,pos=strExp->Find("xb");CString strTmp,strDF;char ch;double dx;while(pos!=-1){dx=0;strTmp="";strDF="";strExp->Delete(pos,2);for(i=pos-1;i>=0;i--){ch=strExp->GetAt(i);if(ch>=50 && ch<=57 || ch>=97 && ch<=102){*strExp="ERROR_二进制数越界_";return;}if(ch=='0' || ch=='1' ||ch==46){strTmp.Insert(0,strExp->Mid(i,1));strExp->Delete(i);}else break;}if(i==pos-1) {*strExp="ERROR_缺少二元运算符_";return;}index=i;pos=strTmp.Find(".");if(pos!=-1){strDF=strTmp.Right(strTmp.GetLength()-pos-1);strTmp.Delete(pos,strTmp.GetLength()-pos);}strTmp.MakeReverse();len=strTmp.GetLength();for(i=0;i<len;i++){ch=strTmp.GetAt(i);dx+=(ch-48)*pow(2,i);}len=strDF.GetLength();for(i=0;i<len;i++){ch=strDF.GetAt(i);dx+=(ch-48)*pow(2,-i-1);}strTmp=NtoS(dx);strExp->Insert(index+1,strTmp);pos=strExp->Find("xb");}}void CCalculation::Dec2Hex(CString *strExp/*strExp须为数字*/) {bool bMinus=0;if(strExp->GetAt(0)=='-'){bMinus=1;strExp->Delete(0);}int pos=strExp->Find('.');CString str,strDec;int nDecInt;double dDec;if(pos!=-1){strDec=strExp->Left(pos);nDecInt=atoi(strDec.GetBuffer(0));strDec=strExp->Right(strExp->GetLength()-pos); }else{nDecInt=atoi(strExp->GetBuffer(0));}strExp->Empty();while(nDecInt!=0){int nTmp=nDecInt%16;if(nTmp==10) str="a";else if(nTmp==11) str="b";else if(nTmp==12) str="c";else if(nTmp==13) str="d";else if(nTmp==14) str="e";else if(nTmp==15) str="f";else str.Format("%d",nTmp);nDecInt/=16;strExp->Insert(0,str);}*strExp+=".";if(pos!=-1){dDec=StoN(strDec);int nCount=0;while(dDec!=0){dDec*=16;int nTmp=dDec;if(nTmp==10) str="a";else if(nTmp==11) str="b";else if(nTmp==12) str="c";else if(nTmp==13) str="d";else if(nTmp==14) str="e";else if(nTmp==15) str="f";else str.Format("%d",nTmp);*strExp+=str.Left(pos);dDec-=nTmp;if(++nCount==17) break;}}if(bMinus) strExp->Insert(0,"-");if(strExp->Find("-1")!=-1 && bMinus!=1) *strExp="太大无法表示"; }void CCalculation::Dec2Oct(CString *strExp){bool bMinus=0;if(strExp->GetAt(0)=='-'){bMinus=1;strExp->Delete(0);}int pos=strExp->Find('.');CString str,strDec;int nDecInt;double dDec;if(pos!=-1){strDec=strExp->Left(pos);nDecInt=atoi(strDec.GetBuffer(0));strDec=strExp->Right(strExp->GetLength()-pos);}else{nDecInt=atoi(strExp->GetBuffer(0));}strExp->Empty();while(nDecInt!=0){int nTmp=nDecInt%8;str.Format("%d",nTmp);nDecInt/=8;strExp->Insert(0,str);}*strExp+=".";if(pos!=-1){dDec=StoN(strDec);int nCount=0;while(dDec!=0){dDec*=8;int nTmp=dDec;str.Format("%d",nTmp);*strExp+=str.Left(pos);dDec-=nTmp;if(++nCount==17) break;}}if(bMinus) strExp->Insert(0,"-");}void CCalculation::Dec2Bin(CString *strExp){bool bMinus=0;if(strExp->GetAt(0)=='-'){bMinus=1;strExp->Delete(0);}int pos=strExp->Find('.');CString str,strDec;_int64 nDecInt;double dDec;if(pos!=-1){strDec=strExp->Left(pos);{*strExp="太大无法转换";return;}nDecInt=atoi(strDec.GetBuffer(0));strDec=strExp->Right(strExp->GetLength()-pos);}else{{*strExp="太大无法转换";return;}nDecInt=atoi(strExp->GetBuffer(0));}strExp->Empty();while(nDecInt!=0){_int64 nTmp=nDecInt%2;str.Format("%d",nTmp);nDecInt/=2;strExp->Insert(0,str);}*strExp+=".";if(pos!=-1){dDec=StoN(strDec);int nCount=0;while(dDec!=0){dDec*=2;int nTmp=dDec;str.Format("%d",nTmp);*strExp+=str.Left(pos);dDec-=nTmp;if(++nCount==17) break;}}if(bMinus) strExp->Insert(0,"-");}六、结论与心得体会七测试结果1.测试+ - * / PI运算2.测试sin cos tan cot3. 20的二进制八进制十六进制二进制八进制十六进制4.历史表达式5.错误判断。