2015-05-15 18 views
7

Tôi muốn triển khai cấu trúc dữ liệu cây biểu thức số học đơn giản trong C++, sao cho đối tượng cây biểu thức được khởi tạo bởi: ExprTree(operator, expression1, expression2). Dưới đây là một ví dụ về cách nó nên làm việc:Cấu trúc dữ liệu cây biểu thức

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 

Sau đây là cách mã của tôi trông cho đến nay:

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(); 
} 

Tuy nhiên, tôi nhận được lỗi này khi tôi biên dịch mã:

left of '->write' must point to class/struct/union/generic type 

Tôi sẽ đánh giá cao nếu ai đó giúp tôi với lỗi này và có thể cung cấp một số mẹo về cách tôi nên triển khai cấu trúc dữ liệu này. Btw, tôi rất mới với C++.

+1

Tôi không thấy đoạn mã có liên quan (lệnh gọi tới 'write' hoặc định nghĩa của nó). – Unimportant

+0

Tôi đã chỉnh sửa mã. Nó sẽ đọc 'str' thay vì' write'. – Randolph

+0

Bạn cần thêm kiểu mẫu khi bạn khởi tạo đối tượng: 'ExprTree expr1 ('*', x, y);' Dòng tiếp theo 'ExprTree (' - ', expr1, z) 'yêu cầu một hàm tạo có thể thực hiện 2 loại toán hạng khác nhau. – Unimportant

Trả lời

2

Có một số vấn đề trong mã của bạn:

  1. Bạn sử dụng viên của con trỏ-> điều hành trên các biến thành viên operand1operand2

  2. Bạn cần hai loại khác nhau trong các đối số mẫu để khởi tạo đối tượng với các kiểu đối số khác nhau.

  3. Lớp học/nhà xây dựng không tự động phát hiện các loại như chức năng. Điều đó có nghĩa là bạn không thể làm một việc như ExprTree('*', x, y);. Bạn có các đối số mẫu chỉ định ête hoặc sử dụng hàm mẫu bổ sung để xây dựng đối tượng của lớp mẫu ExprTree. Xem này answer.

  4. Các if (typeid(*operand1) == typeid(ExprTree)) đánh giá trong thời gian chạy, vì vậy bạn sẽ nhận được một lỗi biên dịch vì bạn cố gắng gọi phương thức str() và vượt qua cùng một đối tượng để std :: string

tôi muốn các giải pháp sau đây:

#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; 
} 

Nó ra chuỗi sau:

01.235.
((1.000000 * 2.000000) - 0.500000) 

Bạn có thể dùng thử here.

2

Khi bạn nói:

operand1->str(); 

Bạn nên nói thay vì:

operand1.str(); 

operand1 không phải là một con trỏ nhưng một biến thành viên.

Thông báo lỗi

trái '-> str' phải trỏ đến lớp/struct/đoàn/generic loại

cơ bản nói rằng bên trái của toán tử -> phải là một con trỏ (không phải vậy). (Nó cũng nói rằng nó phải trỏ đến một lớp hoặc tương tự, không phải một số nguyên, ví dụ).

Các vấn đề liên quan