1009 lines
26 KiB
C++
1009 lines
26 KiB
C++
#include "stdafx.h"
|
|
|
|
#include <math.h>
|
|
#include <float.h>
|
|
|
|
#include "KTExpressCalc.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[]=__FILE__;
|
|
#define new DEBUG_NEW
|
|
#endif
|
|
|
|
#define EPS 1.0e-10
|
|
|
|
#ifndef _ttof
|
|
#ifdef _UNICODE
|
|
#define _ttof(s) wcstod(s, NULL)
|
|
#else
|
|
#define _ttof(s) strtod(s, NULL)
|
|
#endif // _UNICODE
|
|
#endif // _ttof
|
|
|
|
typedef double (* lpfnCalcFun1)(double);
|
|
typedef double (* lpfnCalcFun2)(double, double);
|
|
|
|
static double _or(double dX1, double dX2) { return (fabs(dX1) > EPS || fabs(dX2) > EPS); }
|
|
static double _xor(double dX1, double dX2) { return (((fabs(dX1) > EPS ? 1 : -1) * (fabs(dX2) > EPS ? 1 : -1) < 0) ? 1 : 0); }
|
|
static double _and(double dX1, double dX2) { return (fabs(dX1) > EPS && fabs(dX2) > EPS); }
|
|
static double _not(double dX) { return (fabs(dX) < EPS); }
|
|
static double greatthan(double dX1, double dX2) { return (dX1 > dX2); }
|
|
static double lessthan(double dX1, double dX2) { return (dX1 < dX2); }
|
|
static double equal(double dX1, double dX2) { return (fabs(dX1 - dX2) < EPS); }
|
|
static double greatequal(double dX1, double dX2){ return (dX1 >= dX2); }
|
|
static double lessequal(double dX1, double dX2) { return (dX1 <= dX2); }
|
|
static double notequal(double dX1, double dX2) { return (fabs(dX1 - dX2) > EPS); }
|
|
static double add(double dX1, double dX2) { return (dX1 + dX2); }
|
|
static double subtract(double dX1, double dX2) { return (dX1 - dX2); }
|
|
static double multiple(double dX1, double dX2) { return (dX1 * dX2); }
|
|
static double divide(double dX1, double dX2) { return (dX1 / dX2); }
|
|
static double integer(double dX) { return (long(dX)); }
|
|
static double cot(double dX) { return (1.0 / tan(dX)); }
|
|
static double factorial(double dX) { return dX;}
|
|
|
|
static double f_mod(double dX1, double dX2) { return fmod(dX1, dX2);}
|
|
static double f_pow(double dX1, double dX2) { return pow(dX1, dX2);}
|
|
static double f_abs(double dX) { return fabs(dX); }
|
|
static double f_sqrt(double dX) { return sqrt(dX); }
|
|
static double f_exp(double dX) { return exp(dX); }
|
|
static double f_log(double dX) { return log(dX); }
|
|
static double f_log10(double dX) { return log10(dX); }
|
|
static double f_sin(double dX) { return sin(dX); }
|
|
static double f_cos(double dX) { return cos(dX); }
|
|
static double f_tan(double dX) { return tan(dX); }
|
|
static double f_cot(double dX) { return cot(dX); }
|
|
static double f_asin(double dX) { return asin(dX); }
|
|
static double f_acos(double dX) { return acos(dX); }
|
|
static double f_atan(double dX) { return atan(dX); }
|
|
static double f_sinh(double dX) { return sinh(dX); }
|
|
static double f_cosh(double dX) { return cosh(dX); }
|
|
static double f_tanh(double dX) { return tanh(dX); }
|
|
|
|
static KTExpressCalc::CElement::COperator g_pOperator[] =
|
|
{
|
|
{_T("("), KTExpressCalc::eOpeLeftPthis, KTExpressCalc::ePriLeftPthis, 0, NULL},
|
|
{_T(")"), KTExpressCalc::eOpeRightPthis, KTExpressCalc::ePriRightPthis,0, NULL},
|
|
|
|
{_T("IF"), KTExpressCalc::eOpeIf, KTExpressCalc::ePriIfElse, 0, NULL},
|
|
{_T("THEN"), KTExpressCalc::eOpeThen, KTExpressCalc::ePriIfElse, 0, NULL},
|
|
{_T("ELSE"), KTExpressCalc::eOpeElse, KTExpressCalc::ePriIfElse, 0, NULL},
|
|
|
|
{_T("OR"), KTExpressCalc::eOpeOr, KTExpressCalc::ePriOr, 2, _or},
|
|
{_T("XOR"), KTExpressCalc::eOpeXor, KTExpressCalc::ePriOr, 2, _xor},
|
|
{_T("AND"), KTExpressCalc::eOpeAnd, KTExpressCalc::ePriAnd, 2, _and},
|
|
{_T("NOT"), KTExpressCalc::eOpeNot, KTExpressCalc::ePriNot, 1, _not},
|
|
|
|
{_T(">"), KTExpressCalc::eOpeGreatThan, KTExpressCalc::ePriCompare, 2, greatthan},
|
|
{_T("<"), KTExpressCalc::eOpeLessThan, KTExpressCalc::ePriCompare, 2, lessthan},
|
|
{_T("="), KTExpressCalc::eOpeEqual, KTExpressCalc::ePriCompare, 2, equal},
|
|
{_T(">="), KTExpressCalc::eOpeGreatEqual, KTExpressCalc::ePriCompare, 2, greatequal},
|
|
{_T("<="), KTExpressCalc::eOpeLessEqual, KTExpressCalc::ePriCompare, 2, lessequal},
|
|
{_T("!="), KTExpressCalc::eOpeNotEqual, KTExpressCalc::ePriCompare, 2, notequal},
|
|
|
|
{_T("+"), KTExpressCalc::eOpeAdd, KTExpressCalc::ePriSum, 2, add},
|
|
{_T("-"), KTExpressCalc::eOpeSubtract, KTExpressCalc::ePriSum, 2, subtract},
|
|
{_T("*"), KTExpressCalc::eOpeMultiply, KTExpressCalc::ePriMultiple, 2, multiple},
|
|
{_T("/"), KTExpressCalc::eOpeDivide, KTExpressCalc::ePriMultiple, 2, divide},
|
|
{_T("%"), KTExpressCalc::eOpeRemainder, KTExpressCalc::ePriMultiple, 2, f_mod},
|
|
{_T("^"), KTExpressCalc::eOpePower, KTExpressCalc::ePriPower, 2, f_pow},
|
|
{_T("!"), KTExpressCalc::eOpeFactorial, KTExpressCalc::ePriFactorial, -1, factorial},
|
|
|
|
{_T("int"), KTExpressCalc::eOpeFunction, KTExpressCalc::ePriFunction, 1, integer},
|
|
{_T("abs"), KTExpressCalc::eOpeFunction, KTExpressCalc::ePriFunction, 1, f_abs},
|
|
{_T("sqrt"), KTExpressCalc::eOpeFunction, KTExpressCalc::ePriFunction, 1, f_sqrt},
|
|
{_T("exp"), KTExpressCalc::eOpeFunction, KTExpressCalc::ePriFunction, 1, f_exp},
|
|
{_T("ln"), KTExpressCalc::eOpeFunction, KTExpressCalc::ePriFunction, 1, f_log},
|
|
{_T("log"), KTExpressCalc::eOpeFunction, KTExpressCalc::ePriFunction, 1, f_log10},
|
|
{_T("sin"), KTExpressCalc::eOpeFunction, KTExpressCalc::ePriFunction, 1, f_sin},
|
|
{_T("cos"), KTExpressCalc::eOpeFunction, KTExpressCalc::ePriFunction, 1, f_cos},
|
|
{_T("tan"), KTExpressCalc::eOpeFunction, KTExpressCalc::ePriFunction, 1, f_tan},
|
|
{_T("cot"), KTExpressCalc::eOpeFunction, KTExpressCalc::ePriFunction, 1, f_cot},
|
|
{_T("asin"), KTExpressCalc::eOpeFunction, KTExpressCalc::ePriFunction, 1, f_asin},
|
|
{_T("acos"), KTExpressCalc::eOpeFunction, KTExpressCalc::ePriFunction, 1, f_acos},
|
|
{_T("atan"), KTExpressCalc::eOpeFunction, KTExpressCalc::ePriFunction, 1, f_atan},
|
|
{_T("sinh"), KTExpressCalc::eOpeFunction, KTExpressCalc::ePriFunction, 1, f_sinh},
|
|
{_T("cosh"), KTExpressCalc::eOpeFunction, KTExpressCalc::ePriFunction, 1, f_cosh},
|
|
{_T("tanh"), KTExpressCalc::eOpeFunction, KTExpressCalc::ePriFunction, 1, f_tanh},
|
|
};
|
|
|
|
KTExpressCalc::CElement::CElement()
|
|
{
|
|
m_eEleType = KTExpressCalc::eEleUnknown;
|
|
|
|
m_cOperate.m_pszOperate = NULL;
|
|
m_cOperate.m_eOpeType = KTExpressCalc::eOpeUnknown;
|
|
m_cOperate.m_ePriType = KTExpressCalc::ePriUnknown;
|
|
m_cOperate.m_iEleNum = 0;
|
|
m_cOperate.m_pfnCalc = NULL;
|
|
|
|
m_pszVariable = NULL;
|
|
|
|
m_dValue = 0.0;
|
|
}
|
|
|
|
KTExpressCalc::CElement::CElement(const KTExpressCalc::CElement& cEle)
|
|
{
|
|
m_eEleType = KTExpressCalc::eEleUnknown;
|
|
m_cOperate.m_pszOperate = NULL;
|
|
m_cOperate.m_eOpeType = KTExpressCalc::eOpeUnknown;
|
|
m_cOperate.m_ePriType = KTExpressCalc::ePriUnknown;
|
|
m_cOperate.m_iEleNum = 0;
|
|
m_cOperate.m_pfnCalc = NULL;
|
|
m_pszVariable = NULL;
|
|
m_dValue = 0.0;
|
|
|
|
(*this) = cEle;
|
|
}
|
|
|
|
KTExpressCalc::CElement::~CElement()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void KTExpressCalc::CElement::Clear()
|
|
{
|
|
if (m_eEleType == KTExpressCalc::eEleVariable && m_pszVariable != NULL)
|
|
{
|
|
delete [] m_pszVariable;
|
|
m_pszVariable = NULL;
|
|
}
|
|
|
|
m_eEleType = KTExpressCalc::eEleUnknown;
|
|
|
|
m_cOperate.m_pszOperate = NULL;
|
|
m_cOperate.m_eOpeType = KTExpressCalc::eOpeUnknown;
|
|
m_cOperate.m_ePriType = KTExpressCalc::ePriUnknown;
|
|
m_cOperate.m_iEleNum = 0;
|
|
m_cOperate.m_pfnCalc = NULL;
|
|
|
|
m_dValue = 0.0;
|
|
}
|
|
|
|
KTExpressCalc::CElement& KTExpressCalc::CElement::operator=(const KTExpressCalc::CElement& cEle)
|
|
{
|
|
Clear();
|
|
|
|
m_eEleType = cEle.m_eEleType;
|
|
|
|
switch (m_eEleType)
|
|
{
|
|
case KTExpressCalc::eEleConstant: // 数值
|
|
m_dValue = cEle.m_dValue;
|
|
break;
|
|
case KTExpressCalc::eEleVariable: // 变量
|
|
m_pszVariable = _tcsdup(cEle.m_pszVariable);
|
|
break;
|
|
case KTExpressCalc::eEleOperate: // 操作符
|
|
CopyMemory(&m_cOperate, &(cEle.m_cOperate), sizeof(COperator));
|
|
break;
|
|
}
|
|
|
|
return (*this);
|
|
}
|
|
|
|
BOOL KTExpressCalc::CElement::SetElement(CString sElement, BOOL bConstant)
|
|
{
|
|
Clear();
|
|
|
|
// 常数
|
|
if (bConstant)
|
|
{
|
|
m_eEleType = KTExpressCalc::eEleConstant;
|
|
int iFind = sElement.Find(_T('e')) + 1;
|
|
if (iFind > 0 || (iFind = sElement.Find(_T('E')) + 1) > 0)
|
|
m_dValue = _ttof(sElement.Left(iFind)) * pow(10.0, _ttof(sElement.Mid(iFind)));
|
|
else
|
|
m_dValue = _ttof(sElement);
|
|
return TRUE;
|
|
}
|
|
|
|
// 函数
|
|
int iSize = sizeof(g_pOperator) / sizeof(COperator);
|
|
for (int i = 0; i < iSize; i++)
|
|
{
|
|
if (sElement.CompareNoCase(g_pOperator[i].m_pszOperate) == 0)
|
|
{
|
|
m_eEleType = KTExpressCalc::eEleOperate;
|
|
CopyMemory(&m_cOperate, &(g_pOperator[i]), sizeof(COperator));
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
// 变量
|
|
m_eEleType = KTExpressCalc::eEleVariable;
|
|
m_pszVariable = _tcsdup(sElement);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
KTExpressCalc::KTExpressCalc()
|
|
{
|
|
m_pfnGetVariable = NULL;
|
|
m_wParam = 0;
|
|
m_lParam = 0l;
|
|
|
|
m_eErrorCode = KTExpressCalc::eOk;
|
|
}
|
|
|
|
KTExpressCalc::~KTExpressCalc()
|
|
{
|
|
}
|
|
|
|
// 计算表达式
|
|
BOOL KTExpressCalc::Calculate(LPCTSTR pszExpress, double& dResult)
|
|
{
|
|
dResult = 0.0;
|
|
m_eErrorCode = KTExpressCalc::eOk;
|
|
|
|
CListElement lstElement;
|
|
|
|
OnCreateElementList(pszExpress, lstElement);
|
|
if (lstElement.IsEmpty())
|
|
m_eErrorCode = KTExpressCalc::eNullExpress;
|
|
|
|
if (m_eErrorCode != KTExpressCalc::eOk)
|
|
return FALSE;
|
|
|
|
OnCalcElementList(lstElement, dResult);
|
|
|
|
if (m_eErrorCode != KTExpressCalc::eOk)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// 创建元素列表
|
|
BOOL KTExpressCalc::OnCreateElementList(CString sExpress, CListElement& lstElement)
|
|
{
|
|
CElement cElement;
|
|
|
|
int i = 0, iStart;
|
|
int iLen = sExpress.GetLength();
|
|
|
|
TCHAR ch;
|
|
CString sVariable;
|
|
BOOL bExp, bSign, bPoint, bDigit;
|
|
while (i < iLen)
|
|
{
|
|
iStart = i;
|
|
bExp = FALSE;
|
|
bSign = FALSE;
|
|
bPoint = FALSE;
|
|
bDigit = FALSE;
|
|
|
|
ch = sExpress[i++];
|
|
|
|
// 去除空格
|
|
if (ch == _T(' '))
|
|
continue;
|
|
|
|
// 判断是否是数字
|
|
if (_istdigit(ch) || (bPoint = (ch == _T('.'))))
|
|
{
|
|
for (; i < iLen; i++)
|
|
{
|
|
ch = sExpress[i];
|
|
|
|
if (_istdigit(ch))
|
|
{
|
|
bDigit = TRUE;
|
|
continue;
|
|
}
|
|
|
|
if (bExp)
|
|
{
|
|
if (!bPoint && (bPoint = (ch == _T('.'))))
|
|
continue;
|
|
if (!bDigit && !bPoint && !bSign && (bSign = (ch == _T('+') || ch == _T('-'))) && i+1 < iLen && _istdigit(sExpress[i+1]))
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (!bPoint && (bPoint = (ch == _T('.'))))
|
|
continue;
|
|
if ((bExp = (ch == _T('e') || ch == _T('E'))))
|
|
{
|
|
bSign = FALSE;
|
|
bPoint = FALSE;
|
|
bDigit = FALSE;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
cElement.SetElement(sExpress.Mid(iStart, i-iStart), TRUE);
|
|
lstElement.AddTail(cElement);
|
|
|
|
continue;
|
|
}
|
|
|
|
// 判断是否是括号
|
|
if (ch == _T('(') || ch == _T(')'))
|
|
{
|
|
cElement.SetElement(ch, FALSE);
|
|
lstElement.AddTail(cElement);
|
|
|
|
continue;
|
|
}
|
|
|
|
// 判断是否是符号
|
|
if (_istprint(ch) && !_istalnum(ch))
|
|
{
|
|
for (; i < iLen; i++)
|
|
{
|
|
ch = sExpress[i];
|
|
|
|
if (_istprint(ch) && !_istalnum(ch) && ch != _T(' ') && ch != _T('.') && ch != _T('(') && ch != _T(')'))
|
|
continue;
|
|
|
|
break;
|
|
}
|
|
|
|
cElement.SetElement(sExpress.Mid(iStart, i-iStart), FALSE);
|
|
lstElement.AddTail(cElement);
|
|
|
|
continue;
|
|
}
|
|
|
|
// 判断是否为汉字
|
|
if (!_istprint(ch) && i < iLen)
|
|
i++;
|
|
// 判断是否是字母字串
|
|
for (; i < iLen; i++)
|
|
{
|
|
ch = sExpress[i];
|
|
|
|
if (_istalnum(ch) || ch == _T('_'))
|
|
continue;
|
|
|
|
if (!_istprint(ch) && i+1 < iLen)
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
sVariable = sExpress.Mid(iStart, i-iStart);
|
|
if (sVariable.CompareNoCase(_T("ELSEIF")) == 0)
|
|
{
|
|
cElement.SetElement(_T("ELSE"), FALSE);
|
|
lstElement.AddTail(cElement);
|
|
sVariable = _T("IF");
|
|
}
|
|
cElement.SetElement(sVariable, FALSE);
|
|
lstElement.AddTail(cElement);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// 计算元素列表
|
|
BOOL KTExpressCalc::OnCalcElementList(CListElement& lstElement, double& dResult)
|
|
{
|
|
CListElement lstStack;
|
|
double dValue1, dValue2;
|
|
CElement cElement, cEleVar, cEleOpe;
|
|
while (!lstElement.IsEmpty())
|
|
{
|
|
cElement = lstElement.RemoveHead();
|
|
|
|
// 操作符
|
|
if (cElement.m_eEleType == KTExpressCalc::eEleOperate)
|
|
{
|
|
switch (cElement.m_cOperate.m_eOpeType)
|
|
{
|
|
case KTExpressCalc::eOpeLeftPthis: // 左括号 (...
|
|
// 压栈
|
|
lstStack.AddTail(cElement);
|
|
continue;
|
|
case KTExpressCalc::eOpeRightPthis: // 右括号 )
|
|
// 取出操作数
|
|
if (!OnPopTailVariable(lstStack, cEleVar))
|
|
return FALSE;
|
|
// 取出操作符
|
|
if (!OnPopTailOperator(lstStack, cEleOpe))
|
|
return FALSE;
|
|
// 如果不是左括号
|
|
while (cEleOpe.m_cOperate.m_eOpeType != KTExpressCalc::eOpeLeftPthis)
|
|
{
|
|
// 取出变量值
|
|
if (!OnGetElementValue(cEleVar, dValue2))
|
|
return FALSE;
|
|
// 是否是单目运算
|
|
switch (cEleOpe.m_cOperate.m_iEleNum)
|
|
{
|
|
case 1:
|
|
// 计算
|
|
dValue2 = ((lpfnCalcFun1)(cEleOpe.m_cOperate.m_pfnCalc))(dValue2);
|
|
if (!_finite(dValue2))
|
|
{
|
|
m_eErrorCode = KTExpressCalc::eOutOfBound;
|
|
dValue2 = 0.0;
|
|
return FALSE;
|
|
}
|
|
break;
|
|
case 2:
|
|
// 取出操作数
|
|
if (!OnPopTailVariable(lstStack, cEleVar))
|
|
{
|
|
if (cEleOpe.m_cOperate.m_eOpeType == KTExpressCalc::eOpeAdd
|
|
|| cEleOpe.m_cOperate.m_eOpeType == KTExpressCalc::eOpeSubtract)
|
|
{
|
|
cEleVar.Clear();
|
|
cEleVar.m_eEleType = KTExpressCalc::eEleConstant;
|
|
cEleVar.m_dValue = 0.0;
|
|
m_eErrorCode = KTExpressCalc::eOk;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
// 取出变量值
|
|
if (!OnGetElementValue(cEleVar, dValue1))
|
|
return FALSE;
|
|
// 计算
|
|
dValue2 = ((lpfnCalcFun2)(cEleOpe.m_cOperate.m_pfnCalc))(dValue1, dValue2);
|
|
if (!_finite(dValue2))
|
|
{
|
|
m_eErrorCode = KTExpressCalc::eOutOfBound;
|
|
dValue2 = 0.0;
|
|
return FALSE;
|
|
}
|
|
break;
|
|
default:
|
|
m_eErrorCode = KTExpressCalc::eMissOperator;
|
|
return FALSE;
|
|
}
|
|
// 构造操作数
|
|
cEleVar.Clear();
|
|
cEleVar.m_eEleType = KTExpressCalc::eEleConstant;
|
|
cEleVar.m_dValue = dValue2;
|
|
|
|
// 取出操作符
|
|
if (!OnPopTailOperator(lstStack, cEleOpe))
|
|
return FALSE;
|
|
}
|
|
// 操作数压栈
|
|
lstElement.AddHead(cEleVar);
|
|
// 栈为空
|
|
if (lstStack.IsEmpty())
|
|
continue;
|
|
// 取出操作符
|
|
if (!OnPopTailOperator(lstStack, cElement))
|
|
return FALSE;
|
|
// (, if
|
|
if (cElement.m_cOperate.m_eOpeType == KTExpressCalc::eOpeLeftPthis
|
|
|| cElement.m_cOperate.m_eOpeType == KTExpressCalc::eOpeIf)
|
|
{
|
|
// 压回栈
|
|
lstStack.AddTail(cElement);
|
|
continue;
|
|
}
|
|
break;
|
|
case KTExpressCalc::eOpeIf: // if...
|
|
// 压栈
|
|
lstStack.AddTail(cElement);
|
|
continue;
|
|
case KTExpressCalc::eOpeThen: // then...
|
|
// 取出操作数
|
|
if (!OnPopTailVariable(lstStack, cEleVar))
|
|
return FALSE;
|
|
// 取出操作符
|
|
if (!OnPopTailOperator(lstStack, cEleOpe))
|
|
return FALSE;
|
|
// 如果不是if,则必定是单目运算
|
|
while (cEleOpe.m_cOperate.m_eOpeType != KTExpressCalc::eOpeIf)
|
|
{
|
|
// 取出变量值
|
|
if (!OnGetElementValue(cEleVar, dValue2))
|
|
return FALSE;
|
|
// 是否是单目运算
|
|
switch (cEleOpe.m_cOperate.m_iEleNum)
|
|
{
|
|
case 1:
|
|
// 计算
|
|
dValue2 = ((lpfnCalcFun1)(cEleOpe.m_cOperate.m_pfnCalc))(dValue2);
|
|
if (!_finite(dValue2))
|
|
{
|
|
m_eErrorCode = KTExpressCalc::eOutOfBound;
|
|
dValue2 = 0.0;
|
|
return FALSE;
|
|
}
|
|
break;
|
|
case 2:
|
|
// 取出操作数
|
|
if (!OnPopTailVariable(lstStack, cEleVar))
|
|
{
|
|
if (cEleOpe.m_cOperate.m_eOpeType == KTExpressCalc::eOpeAdd
|
|
|| cEleOpe.m_cOperate.m_eOpeType == KTExpressCalc::eOpeSubtract)
|
|
{
|
|
cEleVar.Clear();
|
|
cEleVar.m_eEleType = KTExpressCalc::eEleConstant;
|
|
cEleVar.m_dValue = 0.0;
|
|
m_eErrorCode = KTExpressCalc::eOk;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
// 取出变量值
|
|
if (!OnGetElementValue(cEleVar, dValue1))
|
|
return FALSE;
|
|
// 计算
|
|
dValue2 = ((lpfnCalcFun2)(cEleOpe.m_cOperate.m_pfnCalc))(0.0, dValue2);
|
|
if (!_finite(dValue2))
|
|
{
|
|
m_eErrorCode = KTExpressCalc::eOutOfBound;
|
|
dValue2 = 0.0;
|
|
return FALSE;
|
|
}
|
|
break;
|
|
default:
|
|
m_eErrorCode = KTExpressCalc::eMissOperator;
|
|
return FALSE;
|
|
}
|
|
// 构造操作数
|
|
cEleVar.Clear();
|
|
cEleVar.m_eEleType = KTExpressCalc::eEleConstant;
|
|
cEleVar.m_dValue = dValue2;
|
|
// 取出操作符
|
|
if (!OnPopTailOperator(lstStack, cEleOpe))
|
|
return FALSE;
|
|
}
|
|
// 分支判断,去除不执行的分支
|
|
if (!OnGetElementValue(cEleVar, dValue1) || !OnCutOneOfIfThenElse(lstElement, fabs(dValue1) < EPS))
|
|
return FALSE;
|
|
// 栈为空
|
|
if (lstStack.IsEmpty())
|
|
continue;
|
|
// 取出操作符
|
|
if (!OnPopTailOperator(lstStack, cElement))
|
|
return FALSE;
|
|
// (, if
|
|
if (cElement.m_cOperate.m_eOpeType == KTExpressCalc::eOpeLeftPthis
|
|
|| cElement.m_cOperate.m_eOpeType == KTExpressCalc::eOpeIf)
|
|
{
|
|
// 压回栈
|
|
lstStack.AddTail(cElement);
|
|
continue;
|
|
}
|
|
break;
|
|
case KTExpressCalc::eOpeElse: // else...
|
|
m_eErrorCode = KTExpressCalc::eMissThen;
|
|
return FALSE;
|
|
}
|
|
|
|
cEleOpe = cElement;
|
|
while (!lstElement.IsEmpty())
|
|
{
|
|
// 将后面运算符比当前优先级还高的运算符压栈
|
|
if (OnNextPriTypeIsHigherThis(lstElement, cEleOpe))
|
|
{
|
|
lstStack.AddTail(cEleOpe);
|
|
break;
|
|
}
|
|
|
|
// 其他操作符运算,碰到( if 即结束
|
|
switch (cEleOpe.m_cOperate.m_iEleNum)
|
|
{
|
|
case -1:
|
|
// 取出操作数
|
|
if (!OnPopTailVariable(lstStack, cEleVar))
|
|
return FALSE;
|
|
// 取出变量值
|
|
if (!OnGetElementValue(cEleVar, dValue2))
|
|
return FALSE;
|
|
// 计算
|
|
dValue2 = ((lpfnCalcFun1)(cEleOpe.m_cOperate.m_pfnCalc))(dValue2);
|
|
if (!_finite(dValue2))
|
|
{
|
|
m_eErrorCode = KTExpressCalc::eOutOfBound;
|
|
dValue2 = 0.0;
|
|
return FALSE;
|
|
}
|
|
break;
|
|
case 1:
|
|
// 取出操作数
|
|
if (!OnPopHeadVariable(lstElement, cEleVar))
|
|
return FALSE;
|
|
// 取出变量值
|
|
if (!OnGetElementValue(cEleVar, dValue2))
|
|
return FALSE;
|
|
// 计算
|
|
dValue2 = ((lpfnCalcFun1)(cEleOpe.m_cOperate.m_pfnCalc))(dValue2);
|
|
if (!_finite(dValue2))
|
|
{
|
|
m_eErrorCode = KTExpressCalc::eOutOfBound;
|
|
dValue2 = 0.0;
|
|
return FALSE;
|
|
}
|
|
break;
|
|
case 2:
|
|
// 取出第2个操作数
|
|
if (!OnPopHeadVariable(lstElement, cEleVar))
|
|
return FALSE;
|
|
// 取出变量值
|
|
if (!OnGetElementValue(cEleVar, dValue2))
|
|
return FALSE;
|
|
// 取出第1个操作数
|
|
if (!OnPopTailVariable(lstStack, cEleVar))
|
|
{
|
|
if (cEleOpe.m_cOperate.m_eOpeType == KTExpressCalc::eOpeAdd
|
|
|| cEleOpe.m_cOperate.m_eOpeType == KTExpressCalc::eOpeSubtract)
|
|
{
|
|
cEleVar.Clear();
|
|
cEleVar.m_eEleType = KTExpressCalc::eEleConstant;
|
|
cEleVar.m_dValue = 0.0;
|
|
m_eErrorCode = KTExpressCalc::eOk;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
// 取出变量值
|
|
if (!OnGetElementValue(cEleVar, dValue1))
|
|
return FALSE;
|
|
// 计算
|
|
dValue2 = ((lpfnCalcFun2)(cEleOpe.m_cOperate.m_pfnCalc))(dValue1, dValue2);
|
|
if (!_finite(dValue2))
|
|
{
|
|
m_eErrorCode = KTExpressCalc::eOutOfBound;
|
|
dValue2 = 0.0;
|
|
return FALSE;
|
|
}
|
|
break;
|
|
default:
|
|
m_eErrorCode = KTExpressCalc::eInvalidOperator;
|
|
return FALSE;
|
|
}
|
|
|
|
// 压回栈中
|
|
cElement.Clear();
|
|
cElement.m_eEleType = KTExpressCalc::eEleConstant;
|
|
cElement.m_dValue = dValue2;
|
|
lstElement.AddHead(cElement);
|
|
|
|
if (lstStack.IsEmpty())
|
|
break;
|
|
|
|
// 取出栈中元素
|
|
cElement = lstStack.GetTail();
|
|
|
|
// 是否是操作符
|
|
if (cElement.m_eEleType != KTExpressCalc::eEleOperate)
|
|
{
|
|
m_eErrorCode = KTExpressCalc::eMissOperator;
|
|
return FALSE;
|
|
}
|
|
|
|
// 如果是if和(
|
|
if (cElement.m_cOperate.m_eOpeType == KTExpressCalc::eOpeIf
|
|
|| cElement.m_cOperate.m_eOpeType == KTExpressCalc::eOpeLeftPthis)
|
|
break;
|
|
|
|
cEleOpe = lstStack.RemoveTail();
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
// 判断是否有操作符
|
|
if (!lstStack.IsEmpty() && lstStack.GetTail().m_eEleType != KTExpressCalc::eEleOperate)
|
|
{
|
|
m_eErrorCode = KTExpressCalc::eMissOperator;
|
|
return FALSE;
|
|
}
|
|
|
|
lstStack.AddTail(cElement);
|
|
}
|
|
|
|
// 取出操作数
|
|
if (!OnPopTailVariable(lstStack, cEleVar))
|
|
return FALSE;
|
|
|
|
// 如果栈中有多项
|
|
while (!lstStack.IsEmpty())
|
|
{
|
|
// 取出操作符
|
|
if (!OnPopTailOperator(lstStack, cEleOpe))
|
|
return FALSE;
|
|
// 取出变量值
|
|
if (!OnGetElementValue(cEleVar, dValue2))
|
|
return FALSE;
|
|
// 是否是单目运算
|
|
switch (cEleOpe.m_cOperate.m_iEleNum)
|
|
{
|
|
case 1:
|
|
// 计算
|
|
dValue2 = ((lpfnCalcFun1)(cEleOpe.m_cOperate.m_pfnCalc))(dValue2);
|
|
if (!_finite(dValue2))
|
|
{
|
|
m_eErrorCode = KTExpressCalc::eOutOfBound;
|
|
dValue2 = 0.0;
|
|
return FALSE;
|
|
}
|
|
break;
|
|
case 2:
|
|
// 取出操作数
|
|
if (!OnPopTailVariable(lstStack, cEleVar))
|
|
{
|
|
if (cEleOpe.m_cOperate.m_eOpeType == KTExpressCalc::eOpeAdd
|
|
|| cEleOpe.m_cOperate.m_eOpeType == KTExpressCalc::eOpeSubtract)
|
|
{
|
|
cEleVar.Clear();
|
|
cEleVar.m_eEleType = KTExpressCalc::eEleConstant;
|
|
cEleVar.m_dValue = 0.0;
|
|
m_eErrorCode = KTExpressCalc::eOk;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
// 取出变量值
|
|
if (!OnGetElementValue(cEleVar, dValue1))
|
|
return FALSE;
|
|
// 计算
|
|
dValue2 = ((lpfnCalcFun2)(cEleOpe.m_cOperate.m_pfnCalc))(dValue1, dValue2);
|
|
if (!_finite(dValue2))
|
|
{
|
|
m_eErrorCode = KTExpressCalc::eOutOfBound;
|
|
dValue2 = 0.0;
|
|
return FALSE;
|
|
}
|
|
break;
|
|
default:
|
|
m_eErrorCode = KTExpressCalc::eMissOperator;
|
|
return FALSE;
|
|
}
|
|
// 构造操作数
|
|
cEleVar.Clear();
|
|
cEleVar.m_eEleType = KTExpressCalc::eEleConstant;
|
|
cEleVar.m_dValue = dValue2;
|
|
}
|
|
|
|
// 取出变量值
|
|
if (!OnGetElementValue(cEleVar, dResult))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// 弹出尾部操作符
|
|
BOOL KTExpressCalc::OnPopTailOperator(CListElement& lstElement, CElement& cEleOpe)
|
|
{
|
|
// 是否为空
|
|
if (lstElement.IsEmpty())
|
|
{
|
|
m_eErrorCode = KTExpressCalc::eMissOperator;
|
|
return FALSE;
|
|
}
|
|
|
|
// 弹出操作符
|
|
cEleOpe = lstElement.RemoveTail();
|
|
|
|
// 判断操作符是否合法
|
|
if (cEleOpe.m_eEleType == KTExpressCalc::eEleOperate)
|
|
return TRUE;
|
|
|
|
// 压回栈
|
|
lstElement.AddTail(cEleOpe);
|
|
|
|
m_eErrorCode = KTExpressCalc::eMissOperator;
|
|
return FALSE;
|
|
}
|
|
|
|
// 弹出头部操作数
|
|
BOOL KTExpressCalc::OnPopHeadVariable(CListElement& lstElement, CElement& cEleVar)
|
|
{
|
|
// 是否为空
|
|
if (lstElement.IsEmpty())
|
|
{
|
|
m_eErrorCode = KTExpressCalc::eMissVariable;
|
|
return FALSE;
|
|
}
|
|
|
|
// 弹出操作数
|
|
cEleVar = lstElement.RemoveHead();
|
|
|
|
// 判断操作数是否合法
|
|
if (cEleVar.m_eEleType == KTExpressCalc::eEleConstant
|
|
|| cEleVar.m_eEleType == KTExpressCalc::eEleVariable)
|
|
return TRUE;
|
|
|
|
// 压回栈
|
|
lstElement.AddHead(cEleVar);
|
|
|
|
m_eErrorCode = KTExpressCalc::eMissVariable;
|
|
return FALSE;
|
|
}
|
|
|
|
// 弹出尾部操作数
|
|
BOOL KTExpressCalc::OnPopTailVariable(CListElement& lstElement, CElement& cEleVar)
|
|
{
|
|
// 是否为空
|
|
if (lstElement.IsEmpty())
|
|
{
|
|
m_eErrorCode = KTExpressCalc::eMissVariable;
|
|
return FALSE;
|
|
}
|
|
|
|
// 弹出操作数
|
|
cEleVar = lstElement.RemoveTail();
|
|
|
|
// 判断操作数是否合法
|
|
if (cEleVar.m_eEleType == KTExpressCalc::eEleConstant
|
|
|| cEleVar.m_eEleType == KTExpressCalc::eEleVariable)
|
|
return TRUE;
|
|
|
|
// 压回栈
|
|
lstElement.AddTail(cEleVar);
|
|
|
|
m_eErrorCode = KTExpressCalc::eMissVariable;
|
|
return FALSE;
|
|
}
|
|
|
|
// 取得元素值
|
|
BOOL KTExpressCalc::OnGetElementValue(CElement& cEleVar, double& dValue)
|
|
{
|
|
if (cEleVar.m_eEleType == KTExpressCalc::eEleConstant)
|
|
{
|
|
dValue = cEleVar.m_dValue;
|
|
return TRUE;
|
|
}
|
|
|
|
if (cEleVar.m_eEleType == KTExpressCalc::eEleVariable && OnGetVariable(cEleVar.m_pszVariable, dValue))
|
|
return TRUE;
|
|
|
|
m_eErrorCode = KTExpressCalc::eInvalidVariable;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// 根据条件去除if-then-else分支中的一条
|
|
BOOL KTExpressCalc::OnCutOneOfIfThenElse(CListElement& lstElement, BOOL bElse)
|
|
{
|
|
int iStack = 1;
|
|
CElement cElement;
|
|
POSITION posBak = NULL;
|
|
POSITION pos = lstElement.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
posBak = pos;
|
|
cElement = lstElement.GetNext(pos);
|
|
|
|
if (cElement.m_eEleType == KTExpressCalc::eEleOperate)
|
|
{
|
|
// 嵌套if
|
|
if (cElement.m_cOperate.m_eOpeType == KTExpressCalc::eOpeIf)
|
|
iStack++;
|
|
else if (cElement.m_cOperate.m_eOpeType == KTExpressCalc::eOpeElse)
|
|
{
|
|
iStack--;
|
|
if (iStack == 0)
|
|
pos = NULL;
|
|
}
|
|
}
|
|
|
|
if (bElse)
|
|
lstElement.RemoveAt(posBak);
|
|
}
|
|
|
|
if (iStack > 0)
|
|
{
|
|
m_eErrorCode = KTExpressCalc::eMissElse;
|
|
return FALSE;
|
|
}
|
|
|
|
if (bElse)
|
|
return TRUE;
|
|
|
|
iStack = 1;
|
|
pos = posBak;
|
|
while (pos != NULL)
|
|
{
|
|
posBak = pos;
|
|
cElement = lstElement.GetNext(pos);
|
|
|
|
if (cElement.m_eEleType == KTExpressCalc::eEleOperate)
|
|
{
|
|
// 嵌套(
|
|
if (cElement.m_cOperate.m_eOpeType == KTExpressCalc::eOpeLeftPthis)
|
|
iStack++;
|
|
else if (cElement.m_cOperate.m_eOpeType == KTExpressCalc::eOpeRightPthis)
|
|
{
|
|
iStack--;
|
|
if (iStack == 0)
|
|
break;
|
|
}
|
|
}
|
|
|
|
lstElement.RemoveAt(posBak);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// 判断是否后面的运算符比给定的优先级高
|
|
BOOL KTExpressCalc::OnNextPriTypeIsHigherThis(CListElement& lstElement, CElement& cEleOpe)
|
|
{
|
|
CElement cElement;
|
|
POSITION pos = lstElement.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
cElement = lstElement.GetNext(pos);
|
|
if (cElement.m_eEleType == KTExpressCalc::eEleOperate)
|
|
{
|
|
if (cElement.m_cOperate.m_ePriType > cEleOpe.m_cOperate.m_ePriType)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// 设置变量数据
|
|
void KTExpressCalc::SetVariableData(LPCTSTR pszVariable, double dValue)
|
|
{
|
|
ASSERT(pszVariable != NULL && _tcslen(pszVariable) > 0);
|
|
m_mapVariable.SetAt(pszVariable, dValue);
|
|
}
|
|
|
|
// 取得变量数据
|
|
BOOL KTExpressCalc::GetVariableData(LPCTSTR pszVariable, double& dValue) const
|
|
{
|
|
ASSERT(pszVariable != NULL && _tcslen(pszVariable) > 0);
|
|
return m_mapVariable.Lookup(pszVariable, dValue);
|
|
}
|
|
|
|
// 设置变量数据,当传入为NULL时,清除变量数据
|
|
void KTExpressCalc::SetVariableData(const CMapStringToDouble* pMapVariable)
|
|
{
|
|
if (pMapVariable == NULL)
|
|
{
|
|
m_mapVariable.RemoveAll();
|
|
}
|
|
else
|
|
{
|
|
double dValue;
|
|
CString sVariable;
|
|
POSITION pos = pMapVariable->GetStartPosition();
|
|
while (pos != NULL)
|
|
{
|
|
pMapVariable->GetNextAssoc(pos, sVariable, dValue);
|
|
m_mapVariable.SetAt(sVariable, dValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 设置取变量值回调函数,当传入为NULL时,清除回调函数
|
|
void KTExpressCalc::SetVariableProc(lpfnGetVariableProc pfnProc, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
m_pfnGetVariable = pfnProc;
|
|
m_wParam = wParam;
|
|
m_lParam = lParam;
|
|
}
|
|
|
|
// 取得变量值
|
|
BOOL KTExpressCalc::OnGetVariable(LPCTSTR pszVariable, double& dValue)
|
|
{
|
|
if (m_mapVariable.Lookup(pszVariable, dValue))
|
|
return TRUE;
|
|
|
|
if (m_pfnGetVariable != NULL && m_pfnGetVariable(pszVariable, dValue, m_wParam, m_lParam))
|
|
return TRUE;
|
|
|
|
m_eErrorCode = KTExpressCalc::eVarialbeNotFind;
|
|
return FALSE;
|
|
}
|
|
|
|
// 取得错误代码
|
|
KTExpressCalc::EErrorCode KTExpressCalc::GetErrorCode()
|
|
{
|
|
return m_eErrorCode;
|
|
}
|