题目
编译器如何解析你的代码?答案可能有点复杂。在这个问题中,我们将处理一些相关的和更简单的东西:算术表达式,包括加、减、乘、除和反。一个表达式可以表示为一个树结构,被命名为“表达式树”或“抽象语法树”。例如,表示-(5/6)x(3 +4)的树应该是:
在表达式树中,每个节点要么是运算符节点,要么是数字节点。对于每个操作符节点,都有指向其操作数的边。注意,运算符’-‘可以是’3 - 2’中的减法运算符,也可以是’-(2 + 3)'中的否定运算符。我们希望能够通过调用适当的函数来创建这样的树,然后对表达式求值或打印表达式的完整圆括号表示。您只需要关注树的建模和不同类型的节点,而不需要关心如何解析表达式。(您将学习如何在CS131中构建解析器。)我们将设计一个可重用的面向对象的解决方案来解决这个问题。不同类型的节点由不同的类表示,所有这些类都派生自一个抽象基类:
代码
#include <iostream>
#include <string>
#include<math.h>
class Expr_node {
public:
Expr_node() = default;//显式缺省(告知编译器生成函数默认的缺省版本)
virtual double eval() const = 0;//返回表达式的值
virtual std::string to_string() const = 0;//返回表达时的字符串形式
virtual ~Expr_node() = default;//析构
Expr_node(const Expr_node&) = delete;//显式删除(告知编译器不生成函数默认的缺省版本)
Expr_node& operator=(const Expr_node&) = delete;//不复制
};
class Number_node : public Expr_node {
friend Number_node* make_number(double);
double value;
Number_node(double val) : value(val) {}
virtual double eval() const override;
virtual std::string to_string() const override;
};
inline Number_node* make_number(double value) {
return new Number_node(value);
}
class Negation_node : public Expr_node {
friend Negation_node* make_negation(Expr_node*);
Expr_node* next;
Negation_node(Expr_node* e) : next(e) {}
virtual double eval() const override;
virtual std::string to_string() const override;
};
inline Negation_node* make_negation(Expr_node* e) {
return new Negation_node(e);
}
class Binary_node : public Expr_node {
protected:
Expr_node *lhs, *rhs;
Binary_node(Expr_node* l, Expr_node* r) : lhs(l), rhs(r){}
};
class Plus_node : public Binary_node {
friend Plus_node* make_plus(Expr_node*, Expr_node*);
Plus_node(Expr_node* l, Expr_node* r) : Binary_node(l,r) {}
virtual double eval() const override;
virtual std::string to_string() const override;
};
inline Plus_node* make_plus(Expr_node* l, Expr_node* r) {
return new Plus_node(l,r);
}
class Minus_node : public Binary_node {
friend Minus_node* make_minus(Expr_node*, Expr_node*);
Minus_node(Expr_node* l, Expr_node* r) : Binary_node(l, r) {}
virtual double eval() const override;
virtual std::string to_string() const override;
};
inline Minus_node* make_minus(Expr_node* l, Expr_node* r) {
return new Minus_node(l, r);
}
class Multiply_node : public Binary_node {
friend Multiply_node* make_multiply(Expr_node*, Expr_node*);
Multiply_node(Expr_node* l, Expr_node* r) : Binary_node(l, r) {}
virtual double eval() const override;
virtual std::string to_string() const override;
};
inline Multiply_node* make_multiply(Expr_node* l, Expr_node* r) {
return new Multiply_node(l, r);
}
class Divide_node : public Binary_node {
friend Divide_node* make_divide(Expr_node*, Expr_node*);
Divide_node(Expr_node* l, Expr_node* r) : Binary_node(l, r) {}
virtual double eval() const override;
virtual std::string to_string() const override;
};
inline Divide_node* make_divide(Expr_node* l, Expr_node* r) {
return new Divide_node(l, r);
}
//part1
/*int main() {
Expr_node* expr_tree = make_divide(
make_plus(make_number(3), make_multiply(make_number(4), make_number(5))),
make_number(6));
std::cout << expr_tree->eval() << std::endl;
std::cout << expr_tree->to_string() << std::endl;
delete expr_tree;
return 0;
}*/
//part2
class Sin_node : public Expr_node {
friend Sin_node* make_sin(Expr_node*);
Expr_node* next;
Sin_node(Expr_node* e) : next(e) {}
virtual double eval() const override;
virtual std::string to_string() const override;
};
inline Sin_node* make_sin(Expr_node* e) {
return new Sin_node(e);
}
class Exp_node : public Expr_node {
friend Exp_node* make_exp(Expr_node*);
Expr_node* next;
Exp_node(Expr_node* e) : next(e) {}
virtual double eval() const override;
virtual std::string to_string() const override;
};
inline Exp_node* make_exp(Expr_node* e) {
return new Exp_node(e);
}
/**/int main() {
Expr_node* expr_tree = make_divide(
make_plus(make_number(3), make_multiply(make_number(4), make_number(5))),
make_number(6));
std::cout << expr_tree->eval() << std::endl;
std::cout << expr_tree->to_string() << std::endl;
delete expr_tree;
Expr_node* bonus_tree =
make_plus(make_exp(make_sin(make_number(3))), make_number(1));
std::cout << bonus_tree->eval() << std::endl;
std::cout << bonus_tree->to_string() << std::endl;
delete bonus_tree;
return 0;
}
double Number_node::eval() const
{
return this->value;
}
std::string Number_node::to_string() const
{
return std::to_string(value);
}
double Negation_node::eval() const
{
return -1.0;
}
std::string Negation_node::to_string() const
{
return "-"+next->to_string();
}
double Plus_node::eval() const
{
return lhs->eval()+rhs->eval();
}
std::string Plus_node::to_string() const
{
return "(" + lhs->to_string() + " + " + rhs->to_string() + ")";
}
double Minus_node::eval() const
{
return lhs->eval() + rhs->eval();
}
std::string Minus_node::to_string() const
{
return "(" + lhs->to_string() + " - " + rhs->to_string() + ")";
}
double Multiply_node::eval() const
{
return lhs->eval()* rhs->eval();
}
std::string Multiply_node::to_string() const
{
return "(" + lhs->to_string() + " * " + rhs->to_string() + ")";
}
double Divide_node::eval() const
{
return lhs->eval() / rhs->eval();
}
std::string Divide_node::to_string() const
{
return "(" + lhs->to_string() + " / " + rhs->to_string() + ")";
}
double Sin_node::eval() const
{
return sin(next->eval());
}
std::string Sin_node::to_string() const
{
return "sin(" + next->to_string()+")";
}
double Exp_node::eval() const
{
return exp(next->eval());
}
std::string Exp_node::to_string() const
{
return "exp(" + next->to_string() + ")";
}
运行结果