提供一个类,字符串表达式解析,不过,表达式容错能力很弱。
源码如下:
class CalcExp
{
public:
CalcExp();
~CalcExp();
double GetResult(LPSTR);
private:
double FindNextValue(LPSTR lpExp, LPSTR &lpRet);
char FindNextOP(LPSTR lpExp, LPSTR &lpRet);
int CompareOP(char chOp1, char chOp2);
int GetLevel(char chOP);
double GetValue(char chOpType, double dLValue, double dRValue);
double CalcExpr(LPSTR);
private:
LPSTR m_pszBuff;
TCHAR m_szBuffForTest[1024];
};
CalcExp::CalcExp()
{
m_pszBuff = NULL;
strcpy(m_szBuffForTest, "");
}
CalcExp::~CalcExp()
{
// delete []m_pszBuff;
}
double CalcExp::FindNextValue(LPSTR lpExp, LPSTR &lpRet)
{
char szTmp[256];
memset(szTmp, 0, 256);
LPSTR lpTmp = szTmp;
while (lpExp && *lpExp != '\0' && (!isdigit(*lpExp)) && (*lpExp != '.'))
{
lpExp ++;
}
BOOL bHasDot = FALSE;
while (lpExp && *lpExp != '\0' && ((isdigit(*lpExp)) || (*lpExp == '.' && !bHasDot)))
{
if(*lpExp == '.')
{
bHasDot = TRUE;
}
*lpTmp = *lpExp;
lpExp ++;
lpTmp++;
}
if(szTmp[0] == 0)
{
lpRet = NULL;
}
else
{
lpRet = lpExp;
}
return atof(szTmp);
}
char CalcExp::FindNextOP(LPSTR lpExp, LPSTR &lpRet)
{
char szOpers[] = "+-*/()";
char chRtn = 0;
while (lpExp && *lpExp != '\0')
{
if(strchr(szOpers, *lpExp))
{
chRtn = *lpExp;
break;
}
lpExp ++;
}
if(lpExp && *lpExp != '\0')
{
lpExp++;
lpRet = lpExp;
}
else
{
lpRet = NULL;
}
return chRtn;
}
int CalcExp::CompareOP(char chOp1, char chOp2)
{
if(chOp2 == ')')
{
return 1;
}
if(chOp1 == '(')
{
return -1;
}
if(chOp2 == '(')
{
return - 1;
}
int iLevel1, iLevel2;
iLevel1 = GetLevel(chOp1);
iLevel2 = GetLevel(chOp2);
if(iLevel1 == iLevel2)
{
return 0;
}
if(iLevel1 > iLevel2)
{
return 1;
}
if(iLevel1 < iLevel2)
{
return -1;
}
}
int CalcExp::GetLevel(char chOP)
{
char szOpers[4][4] = {")","+-","*/", "("};
for(int iLevel = 0; iLevel < 4; iLevel++)
{
if(strchr(szOpers[iLevel], chOP))
{
return iLevel;
}
}
return -1;
}
double CalcExp::CalcExpr(LPSTR lpExp)
{
double dRtn = 0;
while(*lpExp == ' ')
{
lpExp ++;
}
if(*lpExp == '\0')
{
return 0;
}
double ardValueBuff[1024];
char archOPBuff[1024];
int iValDeep = 0, iOPDeep = 0;
LPSTR lpTmpVal = lpExp, lpTmpOP = lpExp;
do
{
ardValueBuff[iValDeep] = FindNextValue(lpTmpVal, lpTmpVal);
if(lpTmpVal)
{
iValDeep++;
}
archOPBuff[iOPDeep] = FindNextOP(lpTmpOP, lpTmpOP);
if(lpTmpOP)
{
iOPDeep++;
}
} while(lpTmpVal || lpTmpOP);
for(int iLoop = 0; iLoop < iValDeep / 2; iLoop++)
{
double dTmp = ardValueBuff[iLoop];
ardValueBuff[iLoop] = ardValueBuff[iValDeep - 1 - iLoop];
ardValueBuff[iValDeep - 1 - iLoop] = dTmp;
}
for(iLoop = 0; iLoop < iOPDeep / 2; iLoop++)
{
char chTmp = archOPBuff[iLoop];
archOPBuff[iLoop] = archOPBuff[iOPDeep - 1 - iLoop];
archOPBuff[iOPDeep - 1 - iLoop] = chTmp;
}
while(iOPDeep)
{
int iValTop = 0, iOPTop = 0;
if(iOPDeep == 1)
{
iOPDeep --;
iValDeep = 0;
dRtn = GetValue(archOPBuff[iOPDeep], ardValueBuff[1], ardValueBuff[0]);
continue;
}
while(CompareOP(archOPBuff[iOPDeep - 1], archOPBuff[iOPDeep - 2]) < 0)
{
iOPDeep--;
iOPTop++;
archOPBuff[1024 - iOPTop] = archOPBuff[iOPDeep];
if(archOPBuff[iOPDeep] == '(')
{
continue;
}
iValDeep--;
iValTop++;
ardValueBuff[1024 - iValTop] = ardValueBuff[iValDeep];
}
iOPDeep--;
if(archOPBuff[iOPDeep] == '(' && archOPBuff[iOPDeep - 1] == ')')
{
iOPDeep--;
}
else
{
iValDeep--;
ardValueBuff[iValDeep - 1] = GetValue(archOPBuff[iOPDeep], ardValueBuff[iValDeep], ardValueBuff[iValDeep - 1]);
}
while(iOPTop || iValTop)
{
if(iOPTop)
{
archOPBuff[iOPDeep] = archOPBuff[1024 -iOPTop];
iOPTop --;
iOPDeep++;
}
if(iValTop)
{
ardValueBuff[iValDeep] = ardValueBuff[1024 - iValTop];
iValTop --;
iValDeep++;
}
}
}
if (iValDeep)
{
dRtn = ardValueBuff[0];
}
return dRtn;
}
double CalcExp::GetValue(char chOpType, double dLValue, double dRValue)
{
switch(chOpType)
{
case '+':
return dLValue + dRValue;
break;
case '-':
return dLValue - dRValue;
break;
case '*':
return dLValue * dRValue;
break;
case '/':
if(dRValue == 0)
{
return 0;
}
return dLValue / dRValue;
break;
}
return 0;
}
double CalcExp::GetResult(LPSTR lpExp)
{
strcpy(m_szBuffForTest, lpExp);
return CalcExpr(lpExp);
}