带科学计数法的有括号四则运算计算器今天交差了,除了输入验证外,基本和需求吻合
代码不多,但是功能还算强大
这里面有我两个得意之处
一是对e的处理, 我把它当成了一个运算符,哈哈,这是个灵感
二是对负号的处理,“-”既可以当作减号也可以当作负号,用个判断就可以了
好了,不多说,看代码吧,开发环境是VC++.NET
// Calculator.h : 头文件
//
#ifndef CALCULATOR_H_2005_04_27__
#define CALCULATOR_H_2005_04_27__
#include <stack>
using namespace std;
typedef stack<double> STACK_DOUBLE;
typedef stack<char> STACK_CHAR;
class CCalculator
{
public :
double CountResult(CString csExp);
int CheckString(CString csExp);
int ReturnError(CString csExp);
CCalculator(void);
private:
STACK_DOUBLE m_doubleStack; //操作数栈
STACK_CHAR m_charStack; //操作符号栈
static char m_priTable[8][8]; //运算符优先级列表
char QueryPri(char chOperator1,char chOperator2);
//查找运算符优先级
//int JudgeOperator(char ch);
// //判断是否为操作符号
int JudgeOperator(CString csExp, int iLocation);
//判断是否为操作符号
double Count(double dbNum1,double dbNum2, char chOper);
//四则运算函数,返回计算结果
double GetCurrentDouble(CString csExpression,int& iCurrentLocation);
//从表达式的当前位置查找操作数并返回,当前位置向前移动
};
#endif
//Calculator.cpp
#include "stdafx.h"
#include "Calculator.h"
#include <stack>
#include <math.h>
using namespace std;
//检查表达式是否合法
int CCalculator::CheckString(CString csExp )
{
return 1;
};
//计算合法表达式的值
double CCalculator::CountResult(CString csExp)
{
int i = 0;
int j = 0;
int iLength = 0;
int& alia_i = i;
char chMyOperator = '\0';
char chCompareResult = '\0';
char chCurrent = '\0';
char chTop = '\0';
double dbNumber1 = 0.0;
double dbNumber2 = 0.0;
double dbResult = 0.0;
double dbCurrentNumber = 0.0;
csExp += "#";
iLength = csExp.GetLength(); //获取表达式的长度
m_charStack.push('#');
for (i=0; i<=iLength; )
{
chCurrent = csExp[i];
if ( JudgeOperator(csExp,i) ) //如果为操作符
{
//比较当前操作符与栈顶操作符的优先级
chTop = m_charStack.top();
chCompareResult = QueryPri(chCurrent, chTop);
switch (chCompareResult)
//根据比较结果执行不同的操作
{
case '>' :
//当前操作符优先级较高,压入操作符号栈
m_charStack.push(chCurrent);
i++;
break;
case '<' :
//当前操作符优先级较小,计算前面的运算结果
chMyOperator = m_charStack.top();
m_charStack.pop();
dbNumber2 = m_doubleStack.top();
m_doubleStack.pop();
dbNumber1 = m_doubleStack.top();
m_doubleStack.pop();
dbResult = Count(dbNumber1, dbNumber2, chMyOperator);
m_doubleStack.push(dbResult);
break;
case '=' :
//当前操作符与栈顶操作符优先级相同,有两种可能
if (chCurrent==')')
//如果为左右括号相遇,脱括号
{
m_charStack.pop();
i++;
break;
}//end if
else
//如果为两个'#'相遇,运算结束
{
if (chCurrent=='#')
{
dbResult = m_doubleStack.top();
return dbResult;
break;
}//end if
}//end else
case 'E' :
//比较出错
break;
default:
break;
}//end switch
}//end if
else
{
dbCurrentNumber = GetCurrentDouble(csExp,alia_i);
m_doubleStack.push(dbCurrentNumber);
}//end else
}//end for
return dbResult;
};
//对不合法的表达式,找到错误,通知用户修改
int CCalculator::ReturnError(CString csExp)
{
return 1;
};
//查找运算符优先级
char CCalculator::QueryPri (char chOperator1, char chOperator2)
{
int i = 0;
int j = 0;
switch (chOperator1)
{
case '+':
i = 0;
break;
case '-':
i = 1;
break;
case '*':
i = 2;
break;
case '/':
i = 3;
break;
case '(':
i = 4;
break;
case ')':
i = 5;
break;
case '#':
i = 6;
break;
case 'e':
i = 7;
break;
default:
break;
};
switch (chOperator2)
{
case '+':
j = 0;
break;
case '-':
j = 1;
break;
case '*':
j = 2;
break;
case '/':
j = 3;
break;
case '(':
j = 4;
break;
case ')':
j = 5;
break;
case '#':
j = 6;
break;
case 'e':
j = 7;
break;
default:
break;
};
return m_priTable[i][j];
};
//初始化运算符优先级列表
char CCalculator::m_priTable[8][8] =
{
//+,,,-,,,*,,,/,,,(,,,),,,#,,,e,
{'<','<','<','<','>','E','>','<'}, //+
{'<','<','<','<','>','E','>','<'}, //-
{'>','>','<','<','>','E','>','<'}, //*
{'>','>','<','<','>','E','>','<'}, ///
{'>','>','>','>','>','E','>','E'}, //(
{'<','<','<','<','=','E','E','<'}, //)
{'<','<','<','<','<','<','=','<'}, //#
{'>','>','>','>','>','E','>','E'} //e
};
//构造函数
CCalculator::CCalculator(void)
{
int i = 0;
stack<double>::size_type double_Length;
stack<char>::size_type char_Length;
if (!(m_doubleStack.empty()))
//初始化操作数栈
{
double_Length = m_doubleStack.size();
for (i=1; i<=double_Length; i++)
{
m_doubleStack.pop();
}//end for
}//end if
if (!(m_charStack.empty()))
//初始化操作符号栈
{
char_Length=m_charStack.size();
for ( i=1; i<=char_Length; i++)
{
m_charStack.pop();
}//end for
}//end if
};
//判断是否为运算符
int CCalculator::JudgeOperator(CString csExp, int iLocation)
{
switch (csExp[iLocation])
{
case '+':
return 1;
break;
case '-':
if (iLocation==0)
{
return 0;
break;
}
else
{ if ((csExp[iLocation-1]=='(') || (csExp[iLocation-1]=='e'))
{
return 0;
break;
}
else
{
return 1;
break;
}
}
return 1;
break;
case '*':
return 1;
break;
case '/':
return 1;
break;
case '(':
return 1;
break;
case ')':
return 1;
break;
case '#':
return 1;
break;
case 'e':
return 1;
break;
default :
return 0;
break;
};
};
//四则运算函数,返回结果
double CCalculator::Count(double dbNum1, double dbNum2, char chOper)
{
double dbResult = 0.0;
switch (chOper)
{
case '+':
dbResult = dbNum1 + dbNum2;
break;
case '-':
dbResult = dbNum1 - dbNum2;
break;
case '*':
dbResult = dbNum1 * dbNum2;
break;
case '/':
if (!(fabs(dbNum2 - 0.0) < 1e-6 ))
{
dbResult = dbNum1 / dbNum2;
}
break;
case 'e':
dbResult = dbNum1 * pow(10.0,dbNum2);
break;
default:
break;
};
return dbResult;
};
//从表达式的当前位置查找操作数并返回,当前位置向前移动
double CCalculator::GetCurrentDouble(CString csExpression,int& iCurrentLocation)
{
int i = 0;
int j = 0;
int iExpressionLength = 0;
int iELocation = 0;
CString csDoubleString("");
char chCurrentChar = '\0';
double dbNumber = 0.0;
i = iCurrentLocation;
iExpressionLength = csExpression.GetLength();
for ( j=i+1; j<iExpressionLength; )
{
chCurrentChar = csExpression[j];
if (!JudgeOperator(csExpression,j))
{
j++;
}//end if
else
{
break;
}//end else
}//end for
csDoubleString = csExpression.Mid(i, j-i);
dbNumber = atof(csDoubleString);
iCurrentLocation = j;
return dbNumber;
};
亲爱的朋友,阅读完本贴之后,请不要吝啬您的留言,无论赞扬或是批评,我都会深深地感谢您!