表达式树数据结构
我想在c ++中实现一个简单的算术表达式树数据结构,以便表达式树对象被初始化为: ExprTree(operator, expression1, expression2)
。 这是一个应该如何工作的例子:
double x = 1, y = 2, z = 0.5;
expr1 = ExprTree('*', x, y); // expr1 = 1 * 2 = 2
expr2 = ExprTree('-', expr1, z); // expr2 = (1 * 2) - 0.5 = 1.5
cout << expr2.str() << endl; // ((1 * 2) - 0.5)
cout << expr2.eval() << endl; // 1.5
下面是我的代码看起来如何:
template<class operand_type>
class ExprTree
{
public:
ExprTree(const char op_, operand_type& operand1_, operand_type& operand2_)
{
op = op_;
operand1 = operand1_;
operand2 = operand2_;
}
double eval() const;
std::string str() const;
private:
char op;
typename operand_type operand1, operand2;
};
template<class operand_type>
std::string ExprTree<operand_type>::str() const
{
std::ostringstream os;
std::string op1, op2;
if (typeid(*operand1) == typeid(ExprTree))
op1 = operand1->str();
else
op1 = std::string(*operand1);
if (typeid(*operand2) == typeid(ExprTree))
op2 = operand1->str();
else
op2 = std::string(*operand2);
os << "(" << op1 << " " << op << " " << op2 << ")";
return os.str();
}
但是,编译代码时出现此错误:
left of '->write' must point to class/struct/union/generic type
我将不胜感激,如果有人会帮助我这个错误,并可能提供一些关于如何实现这个数据结构的提示。 顺便说一句,我对c ++很陌生。
你的代码中有许多问题:
您在成员变量operand1和operand2上使用指针- >运算符的成员
在模板参数中需要两种不同的类型来初始化具有不同参数类型的对象。
类/构造函数不像函数那样自动检测类型。 这意味着你不能像ExprTree('*', x, y);
那样ExprTree('*', x, y);
。 您可以使用ether指定模板参数或使用其他模板函数构造ExprTree模板类的对象。 看到这个答案。
if (typeid(*operand1) == typeid(ExprTree))
在运行时计算,所以你会得到一个编译错误,因为你试图调用方法str()并将同一个对象传递给std :: string
我更喜欢以下解决方案:
#include <string>
#include <iostream>
#include <sstream>
template<typename operand_type_A, typename operand_type_B>
class ExprTree
{
public:
ExprTree(){};
ExprTree(const char op_, const operand_type_A& operand1_, const operand_type_B& operand2_) {
op = op_;
operand1 = operand1_;
operand2 = operand2_;
};
double eval() const;
std::string str() const;
private:
char op;
operand_type_A operand1;
operand_type_B operand2;
};
template<typename operand_type_A, typename operand_type_B>
ExprTree<operand_type_A, operand_type_B> makeExpr(const char op, const operand_type_A& operand1, const operand_type_B& operand2)
{
return ExprTree<operand_type_A, operand_type_B>(op, operand1, operand2);
}
template<typename T>
std::string ToString(const T& x)
{
return x.str();
}
template<>
std::string ToString<double>(const double& x)
{
return std::to_string(x);
}
template<typename operand_type_A, typename operand_type_B>
std::string ExprTree<operand_type_A, operand_type_B>::str() const {
std::ostringstream os;
std::string op1, op2;
op1 = ToString(operand1);
op2 = ToString(operand2);
os << "(" << op1 << " " << op << " " << op2 << ")";
return os.str();
}
int main()
{
double x = 1, y = 2, z = 0.5;
std::cout << makeExpr('-', makeExpr('*', x, y), z).str() << std::endl;
return 0;
}
它输出以下字符串:
((1.000000 * 2.000000) - 0.500000)
你可以在这里尝试。
当你说:
operand1->str();
你应该说:
operand1.str();
因为operand1
不是一个指针而是一个成员变量。
错误消息
' - > str'的左边必须指向class / struct / union / generic类型
基本上说,operator ->
的左边必须是一个指针(不是)。 (它也说它必须指向一个类或类似的,而不是一个整数,例如)。