#include <iostream>
#include <string>
#include <stack>
#include <map>
#include <vector>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <cassert>
class Expression
{
public:
enum OpType
{
NoType,
Operator, // '+', '-', '*', '/'等
Operand, // 数字
BeginSymbol, // '('
EndSymbol, // ')'
};
struct OpData
{
double value;
OpType type;
};
typedef std::vector<OpData> PrefixType;
Expression()
{
m_priority.insert(std::make_pair('+', 0));
m_priority.insert(std::make_pair('-', 0));
m_priority.insert(std::make_pair('*', 1));
m_priority.insert(std::make_pair('/', 1));
}
bool IsOperator(int v) const
{
return m_priority.find(v) != m_priority.end();
}
bool IsOperand(int v) const
{
return v >= '0' && v <= '9' || v == '.';
}
bool IsEndSymbol(int v) const
{
return v == ')';
}
bool IsBeginSymbol(int v) const
{
return v == '(';
}
int GetPriority(int v) const
{
std::map<int, int>::const_iterator itr = m_priority.find(v);
if (itr != m_priority.end())
{
return itr->second;
}
return -1;
}
double GetResult(double a, double b, int op)
{
double r = 0;
switch (op)
{
case '+':
r = a + b;
break;
case '-':
r = a - b;
break;
case '*':
r = a * b;
break;
case '/':
assert(b != 0);
r = a / (double)b;
break;
default:
break;
}
return r;
}
//中缀表达式 转为 前缀表达式
int ToPrefix(const std::string &src, PrefixType &dest)
{
if (src.empty())
{
return -1;
}
std::stack<OpData> s1;
std::stack<OpData> s2;
std::string num;
for (std::string::const_reverse_iterator itr = src.rbegin(); itr != src.rend(); ++itr)
{
const int v = *itr;
if (IsOperand(v))
{
num.push_back(v);
}
else
{
if(!num.empty())
{
std::reverse(num.begin(), num.end());
s2.push(OpData{ atof(num.c_str()), Operand });
num.clear();
}
if (IsOperator(v))
{
while (1)
{
if (s1.empty())
{
s1.push(OpData{ (double)v, Operator });
break;
}
const OpData topV = s1.top();
if (topV.type == EndSymbol || (topV.type == Operator && GetPriority(v) >= GetPriority(topV.value)) )
{
s1.push(OpData{ (double)v, Operator });
break;
}
s2.push(topV);
s1.pop();
}
}
else if (IsEndSymbol(v))
{
s1.push(OpData{ (double)v, EndSymbol });
}
else if (IsBeginSymbol(v))
{
while (!s1.empty())
{
const OpData topV = s1.top();
s1.pop();
if (topV.type == EndSymbol)
{
break;
}
s2.push(topV);
}
}
}
}
if (!num.empty())
{
std::reverse(num.begin(), num.end());
s2.push(OpData{ atof(num.c_str()), Operand });
num.clear();
}
while (!s1.empty())
{
s2.push(s1.top());
s1.pop();
}
while (!s2.empty())
{
dest.push_back(s2.top());
s2.pop();
}
return 0;
}
//int ToPostfix(const std::string &src, std::string &dest) {}
//计算前缀表达式的结果
int CalculatePrefix(const PrefixType & prefix, double &result)
{
std::stack<double> s;
for (PrefixType::const_reverse_iterator itr = prefix.rbegin(); itr != prefix.rend(); ++itr)
{
const OpData v = *itr;
if (v.type == Operand)
{
s.push(v.value);
}
else if (v.type == Operator)
{
if (s.size() < 2)
{
return -2;
}
double a = s.top();
s.pop();
double b = s.top();
s.pop();
double c = GetResult(a, b , v.value);
//std::cout << a << " " << (char)v.value << " " << b << " = " << c << std::endl;
s.push(c);
}
}
if (s.size() != 1)
{
return - 1;
}
result = s.top();
return 0;
}
friend inline std::ostream &operator<<(std::ostream &stream, const Expression::OpData &v)
{
if (v.type == Expression::Operand)
stream << v.value;
else
stream << (char)v.value;
return stream;
}
static std::string ToStr(const Expression::PrefixType &result)
{
std::stringstream ss;
for (Expression::PrefixType::const_iterator itr = result.begin(); itr != result.end(); ++itr)
{
ss << " " << *itr;
}
return ss.str();
}
private:
std::map<int, int> m_priority;
};
int main(int argc, char **argv)
{
std::string src = argc > 1 ? argv[1] : "12+((2+73)*4)-15";
std::cout << "src: " << src << std::endl;
Expression expression;
Expression::PrefixType result;
int ret = expression.ToPrefix(src, result);
if (ret != 0)
{
std::cout << src << " ToPrefix Error." << std::endl;
return 1;
}
std::cout << "prefix: " << Expression::ToStr(result) << std::endl;
double opResult = 0;
ret = expression.CalculatePrefix(result, opResult);
if (ret != 0)
{
std::cout << Expression::ToStr(result) << " Calculate Error." << std::endl;
return 2;
}
std::cout << "calculate: " << opResult << std::endl;
if (argc == 1)
{
assert((int)opResult == 297);
}
getchar();
return 0;
}
后缀表达式计算器代码
最新推荐文章于 2022-12-27 22:01:14 发布