表达式树数据结构

时间:2015-05-15 16:29:50

标签: c++ class tree expression

我想在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 ++很新。

2 个答案:

答案 0 :(得分:2)

当你说:

operand1->str();

你应该说:

operand1.str();

因为operand1不是指针而是成员变量。

错误消息

  < - >'&gt; str'的左边必须指向class / struct / union / generic type

基本上说运算符->的左边必须是指针(它不是)。 (它还说它必须指向一个类或类似的,而不是一个整数,例如)。

答案 1 :(得分:2)

您的代码中存在许多问题:

  1. 您在成员变量 operand1 operand2 <上使用指针成员 - &gt; 运算符/ p>

  2. 模板参数需要两种不同的类型来初始化具有不同参数类型的对象。

  3. 类/构造函数不会像函数那样自动检测类型。这意味着你不能做ExprTree('*', x, y);这样的事情。您有以太指定模板参数或使用其他模板函数来构造 ExprTree 模板类的对象。见answer

  4. if (typeid(*operand1) == typeid(ExprTree))在运行时进行求值,因此您将收到编译错误,因为您尝试调用方法 str()并将同一对象传递给 std ::串

  5. 我更喜欢以下解决方案:

    #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)
    

    您可以尝试here