提供一个类,字符串表达式解析,不过,表达式容错能力很弱。
源码如下:
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); }

|