功能特性
- 支持
+ - * / 四則運算與括號 ()。
- 單一模板函數接口:
int GetExpValue(_Tstream& istrin, _T& nReturn)。
- 輸入源靈活:標準流、文件流、字符串流均可。
- 返回類型由輸出參數
nReturn 決定(int/double 等)。
- 返回非 0 表示成功,0 表示錯誤。
核心代碼
namespace fy_Exp {
namespace {
template
inline _T GetExpValue(_T t[], char& csym) {
char c = csym; csym = 0;
switch (c) {
case '+': return t[0] += t[1];
case '-': return t[0] -= t[1];
case '*': return t[0] *= t[1];
default: return t[0] /= t[1]; // case '/'
}
}
}
template
int GetExpValue(_Tstream& istrin, _T& nReturn) {
_T t[3] = {0};
char csym[3] = "++";
int nLevel = 1, nERR = 0;
if (!(istrin >> t[1])) istrin.clear();
for (;;) {
if (istrin >> csym[2]) {
switch (csym[2]) {
case '(':
if (!csym[1]) { nLevel = 0x100; nERR = 1; }
else if (!GetExpValue(istrin, t[2])) nLevel |= 0x10;
else { nLevel = 0x100; nERR = 1; }
break;
case ')': { nLevel = 0x100; } break;
case '+': case '-': case '*': case '/':
{ csym[nLevel++] = csym[2]; } break;
case ' ': case '\r': case '\n': case '\t': continue;
default: { nLevel = 0x100; nERR = 1; }
}
if (nLevel == 0x100) break;
if (nLevel & 0x10 || istrin >> t[2]) {
nLevel &= 0xF;
if (nLevel == 1) { t[1] = t[2]; csym[1] = 0; continue; }
if (csym[1] == '*' || csym[1] == '/') {
GetExpValue(t + 1, csym[1]);
} else {
GetExpValue(t, csym[0]);
t[1] = t[2]; csym[0] = csym[1]; csym[1] = 0;
}
nLevel = 1;
} else istrin.clear();
} else { nERR = -1; break; }
}
if (csym[1]) t[2] = 0, nReturn = GetExpValue(t + 1, csym[1]);
else nReturn = GetExpValue(t, csym[0]);
return nERR == -1 ? 1 : 0;
}
}
使用示例
#include
#include
#include
using namespace std;
int main() {
string s1;
while (cin >> s1) {
istrstream isin(s1.data());
double d;
if (fy_Exp::GetExpValue(isin, d))
cout << d << endl;
else
cout << "ERROR" << endl;
}
return 0;
}
編譯建議
- TC++ 必報錯;VC6 可能通過但不保證。
- 推薦 VC7+ (VS2003+) 或 GNU G++ 編譯。