几年之前因为一个表达式求值方面的问题烦恼了好几天。最终问题虽然解决了,但对于表达式求值的实现却未理解。大概是因为当初数据结构基础薄弱的缘故吧。好几年了,今天偶尔想起,决定写一个。虽说写,也不是原创,而是在别人的基础上修改而来的。放在这里,以备查阅。
首先是exprcalc.h文件
#ifndef _EXPR_CALC_H_
#define _EXPR_CALC_H_
#include <stack>
#include <string>
#include <exception>
#pragma warning(disable: 4018 4244)
template<class T>
class ExprCalc
...{
public:
ExprCalc(std::string expr) : expr_(expr) ...{ }
void SetExpr(std::string expr) ...{ expr_ = expr; }
T Resolve();
private:
// 处理栈内的元素
void Deal()
...{
char sign = op_.top(); op_.pop();
T x = num_.top(); num_.pop();
T y = num_.top(); num_.pop();
T res = Calc(y, x, sign); num_.push(res);
}
// 计算x sign y, 结果返回,sign= +、-、*、/
T Calc(T x, T y, char sign) 
...{
switch (sign)
...{
case '+': return x + y;
case '-': return x - y;
case '*': return x * y;
case '/': return x / y;
default: throw std::logic_error("Invalid Expression!");
}
}
// 计算符号的优先级
int Prior(char sign) 
...{
if (sign == '*' || sign == '/' || sign == '%') return 2;
if (sign == '+' || sign == '-') return 1;
return 0;
}
private:
std::string expr_; //输入的字符串
std::stack<T> num_; //数据栈
std::stack<char> op_; //符号栈
};
template<class T>
T ExprCalc<T>::Resolve()
...{
if (expr_.length() == 0)
throw std::logic_error("Invalid Expression!");
for (int i = 0; i < expr_.length(); )
...{
// 第一个数是负数,或(-8+9)这种情况
if ((expr_[i] >= '0' && expr_[i] <= '9') ||
(expr_[i] == '-') && (i == 0 || expr_[i-1] == '('))
...{
int j = 0;
char operand[10] = ...{0, };
while ((expr_[i] >= '0' && expr_[i] <= '9') ||
(expr_[i] == '-' && (i == 0 || expr_[i-1] == '(')) ||
(expr_[i] == '.'))
operand[j++] = expr_[i++];
T num = atof(operand);
num_.push(num);
}
else
...{
if (expr_[i] == ')') 
...{
while (op_.top() != '(')
Deal();
op_.pop();
}
else 
...{
if (!op_.empty() && expr_[i] != '(' &&
Prior(expr_[i]) <= Prior(op_.top()))
Deal();
op_.push(expr_[i]);
}
i++;
}
}
while (!op_.empty())
Deal();
T res = num_.top(); num_.pop();
return res;
}
#endif然后是exprcalc.cpp文件
#include "ExprCalc.h"
#include <iostream>
using namespace std;
int main()
...{
try
...{
ExprCalc<int> ec("2*(25+25)+100*500");
cout << ec.Resolve() << endl;
}
catch (const exception& e)
...{
cout << e.what() << endl;
}
return getchar();
}此程序在vs2005下测试通过。
424

被折叠的 条评论
为什么被折叠?



