#pragma once #include #include #include "Tree.h" #include "Node_function.h" #include "Node_variable.h" #include "Node_constant.h" #include "RETURN.h" #include "User.h" #pragma once #include #include template class Node { template friend class Tree; public: Node(int _children_quantity, std::string _alias); virtual ~Node(); virtual void set_args(T *_args) = 0; virtual bool is_completed() const = 0; virtual T get_value() const = 0; int get_childrens_quantity() const; std::string get_alias() const; //protected: int childrens_quantity; std::string alias; std::vector*> childrens; }; //-------------------------------------------------------- template Node::Node(int _children_quantity, std::string _alias) : childrens_quantity(_children_quantity), alias(_alias) { } template Node::~Node() { std::cout << "Destroy: " + alias << '\n'; for (int i = 0; i < childrens.size(); i++) { delete childrens.at(i); } } template std::string Node::get_alias() const { return alias; } template int Node::get_childrens_quantity () const { return childrens_quantity; } #pragma once #include "Node.h" template class Node_constant : public Node { template friend class Tree; public: Node_constant(std::string _alias, T _value); ~Node_constant(); void set_args(T *_args); bool is_completed() const; T get_value() const; //private: T value; }; //-------------------------------------------------------- template Node_constant::Node_constant(std::string _alias, T _value) : Node(0, _alias), value(_value){ } template Node_constant::~Node_constant() { } template void Node_constant::set_args(T *_args) { value = *_args; } template bool Node_constant::is_completed() const { return true; } template T Node_constant::get_value() const { return value; } #pragma once #include "Node.h" template class Node_variable : public Node { template friend class Tree; public: Node_variable(std::string _alias); ~Node_variable(); void set_args(T *_args); bool is_completed() const; T get_value() const; //private: T value; }; //-------------------------------------------------------- template Node_variable::Node_variable(std::string _alias) : Node(0, _alias), value(NULL) { } template Node_variable::~Node_variable() { } template void Node_variable::set_args(T *_args) { value = *_args; } template bool Node_variable::is_completed() const { return true; } template T Node_variable::get_value() const { return value; } #pragma once #include "Node.h" template class Node_function : public Node { template friend class Tree; public: Node_function(std::string _alias, int _args_quantity, T (*_function)(T *_args)); ~Node_function(); void set_args(T *_args); bool is_completed() const; T get_value() const; //private: T *args; T (*function)(T *args); }; //-------------------------------------------------------- template Node_function::Node_function(std::string _alias, int _args_quantity, T(*_function)(T *_args)) : Node(_args_quantity, _alias), args(new T[_args_quantity]), function(_function){ } template Node_function::~Node_function() { delete args; } template void Node_function::set_args(T *_args) { args = _args; } template bool Node_function::is_completed() const { bool result = childrens_quantity == childrens.size(); int i = 0; while (i < childrens_quantity && result) { if (childrens.at(i) == nullptr) { result = false; } else { result = childrens.at(i)->is_completed(); } i++; } return result; } template T Node_function::get_value() const { for (int i = 0; i < childrens.size(); i++) { args[i] = childrens.at(i)->get_value(); } return function(args); } #pragma once #include #include #include #include #include #include #include #include "Node_function.h" #include "Node_variable.h" #include "Node_constant.h" #include "RETURN.h" template class Tree { public: Tree(); ~Tree(); RETURN add_function(std::string _alias, int _args_quantity, T (*_function)(T *_args)); RETURN add_variable(std::string _alias); RETURN add_constant(T _value); RETURN is_completed() const; RETURN calculate(int _args_quantity, T *_args); RETURN vars() const; RETURN print() const; Tree& operator=(const Tree &_other); Tree& operator+(const Tree &_other) const; //private: void set_new(Node *_begin, Node *_new_node); void preorder(Node *_current) const; std::vector*> get_variables() const; Node *root; }; /** Create new Tree and set root as NULL */ template Tree::Tree() : root(nullptr) { } /** Delete Tree, nodes are being deleted in preorder */ template Tree::~Tree() { std::cout << "delete: " << '\n'; delete root; } /** Add new node containing function in first empty place found by preorder algorithm @_alias Name of function @_args_quantity How many arguments function takes @_function Pointer to function to storage in node */ template RETURN Tree::add_function(std::string _alias, int _args_quantity, T(*_function)(T *_args)) { RETURN _return; if (_args_quantity < 0) { _return.set_return_code(error); _return.set_value(false); _return.set_message("Function cannot take negative amount of arguments"); return _return; } if (_function == nullptr) { _return.set_return_code(error); _return.set_value(false); _return.set_message("Pointer to function cannto be null"); return _return; } if (root != nullptr) { if (root->is_completed()) { _return.set_return_code(warning); _return.set_message("Tree is already complete"); return _return; } set_new(root, new Node_function(_alias, _args_quantity, _function)); } else { root = new Node_function(_alias, _args_quantity, *_function); } _return.set_return_code(no_error); _return.set_value(true); return _return; } /** Add new node containing variable in first empty place found by preorder algorithm. @_alias Name of variable */ template RETURN Tree::add_variable(std::string _alias) { RETURN _return; if (_alias == "") { _return.set_return_code(error); _return.set_value(false); _return.set_message("Variable must have a name"); return _return; } if (root != nullptr) { if (root->is_completed()) { _return.set_return_code(warning); _return.set_value(false); _return.set_message("Tree is already complete"); return _return; } set_new(root, new Node_variable(_alias)); } else { root = new Node_variable(_alias); } _return.set_return_code(no_error); _return.set_value(true); return _return; } /** Add new node containg constant in first empty place found by preorder algorithm @_value Value of constant */ template RETURN Tree::add_constant(T _value) { RETURN _return; if (root != nullptr) { if (root->is_completed()) { _return.set_return_code(warning); _return.set_value(false); _return.set_message("Tree is already complete"); return _return; } set_new(root, new Node_constant(std::to_string(_value), _value)); } else { root = new Node_constant(std::to_string(_value), _value); } _return.set_return_code(no_error); _return.set_value(true); return _return; } template RETURN Tree::is_completed() const { RETURN _return; if (root == nullptr) { _return.set_value(false); } else { _return.set_value(root->is_completed()); } _return.set_return_code(no_error); return _return; } /** Calculate value of whole tree @_args Array of values to be put in variables nodes */ template RETURN Tree::calculate(int _args_quantity, T *_args) { RETURN _result; if (_args_quantity < get_variables().size()) { _result.set_return_code(error); _result.set_message("Not enough arguments"); return _result; } if (root == nullptr) { _result.set_return_code(warning); _result.set_message("The tree is empty"); return _result; } else if (!root->is_completed()) { _result.set_return_code(error); _result.set_message("The tree is uncompleted"); return _result; } /* Move through tree and assign all values to nodes containg variables */ int i = 0; std::stack*> stack; stack.push(root); while (!stack.empty()) { Node *current = stack.top(); if (Node_variable *var = dynamic_cast*>(current)) { var->set_args(&_args[i]); i++; } stack.pop(); for (int i = current->childrens.size() - 1; i >= 0; i--) { stack.push(current->childrens.at(i)); } } /* Return value */ _result.set_return_code(no_error); _result.set_value(root->get_value()); return _result; } /** Prints names of all variables in tree without repetitions */ template RETURN Tree::vars() const { RETURN _result; std::string result = ""; std::vector variables; for (int i = 0; i < get_variables().size(); i++) { if (std::find(variables.begin(), variables.end(), get_variables().at(i)->get_alias()) == variables.end()) { variables.push_back(get_variables().at(i)->get_alias()); result += variables.at(i) + ' '; } } _result.set_return_code(no_error); _result.set_value(result); return _result; } template RETURN Tree::print() const { RETURN _return; std::string result = ""; std::stack*> stack; stack.push(root); while (!stack.empty()) { Node *current = stack.top(); result += current->alias + ' '; stack.pop(); for (int i = current->childrens.size() - 1; i >= 0; i--) { stack.push(current->childrens.at(i)); } } _return.set_return_code(no_error); _return.set_value(result); return _return; } /** Assignment operator overload */ template Tree& Tree::operator=(const Tree &_other) { if (this == &_other) return *this; /* Dealocate memoey */ delete root; root = nullptr; /* Move through _other tree and copy all nodes */ std::stack*> stack; stack.push(_other.root); while (!stack.empty()) { Node* current = stack.top(); if (Node_function *fun = dynamic_cast*>(current)) { add_function(fun->get_alias(), fun->get_childrens_quantity(), fun->function); } else if (Node_variable *var = dynamic_cast*>(current)) { add_variable(var->get_alias()); } else if (Node_constant *con = dynamic_cast*>(current)) { add_constant(con->get_value()); } stack.pop(); for (int i = current->childrens.size() - 1; i >= 0; i--) { stack.push(current->childrens.at(i)); } } return *this; } /** */ template Tree& Tree::operator+(const Tree &_other) const { Tree result; result = *this; Node* current = result.root; if (current->childrens.size() > 0) { std::srand (time(NULL)); int i = rand() % current->childrens.size(); Node_function *fun = dynamic_cast*>(current->childrens.at(i)); Node_variable *var = dynamic_cast*>(current->childrens.at(i)); Node_constant *con = dynamic_cast*>(current->childrens.at(i)); while (!fun || !var || !con){ current = current->childrens.at(i); fun = dynamic_cast*>(current->childrens.at(i)); var = dynamic_cast*>(current->childrens.at(i)); con = dynamic_cast*>(current->childrens.at(i)); } delete current->childrens.at(i); fun = dynamic_cast*>(_other.root); var = dynamic_cast*>(_other.root); con = dynamic_cast*>(_other.root); if (fun) { current->childrens.at(i) = new Node_function(fun->alias, fun->childrens_quantity, fun->function); } else if (var) { current->childrens.at(i) = new Node_variable(var->alias); } else { current->childrens.at(i) = new Node_constant(std::to_string(con->get_value()), con->get_value()); } } return result; } /** Adds given node in first empty place found by preorder algorithm which starts searching from pointed node @_begin Node from which searching starts @_new_node New node to be added */ template void Tree::set_new(Node *_begin, Node *_new_node) { bool added = false; //Condition of while loop Node *current = _begin; //Currently used node /* Searching loop */ while (!added) { /* Iterate throught all already completed childes of current node, that is having all childrens */ int i = 0; while (i < current->childrens.size() && current->childrens.at(i)->is_completed()) { i++; } /* Decide if move to next child or add new node */ if (i < current->childrens.size() && !current->childrens.at(i)->is_completed()) { /* Found uncompleted child */ current = current->childrens.at(i); } else { /* All previous childs are complete, thus add new node as child */ current->childrens.push_back(_new_node); added = true; } } } /** Print tree in preorder */ template void Tree::preorder(Node *_current) const { std::cout << _current->get_alias() << ' '; for (int i = 0; i < _current->childrens.size(); i++) { if (_current->childrens[i] != nullptr) { preorder(_current->childrens[i]); } } } /** */ template std::vector*> Tree::get_variables() const { std::vector*> variables; std::stack*> stack; stack.push(root); while (!stack.empty()) { Node *current = stack.top(); if (Node_variable *var = dynamic_cast*>(current)) { variables.push_back(var); } stack.pop(); for (int i = current->childrens.size() - 1; i >= 0; i--) { stack.push(current->childrens.at(i)); /// } } return variables; } #pragma once #include #include enum return_code { no_error, warning, error }; template class RETURN { public: RETURN(); RETURN(return_code _rc); RETURN(const T& _value); void set_return_code(return_code _rc); void set_message(std::string _message); void add_message(std::string _message); void set_value(T _value); bool is_error() const; T get_value() const; std::string get_message() const; RETURN& operator=(const RETURN &_other); private: T value; return_code rc; std::string message; }; template RETURN::RETURN() : message(""){ } template RETURN::RETURN(return_code _rc) : rc(_rc), message("") { } template RETURN::RETURN(const T& _value) : rc(no_error), message(""), value(_value) { } template void RETURN::set_return_code(return_code _rc) { rc = _rc; } template void RETURN::set_message(std::string _message) { message = _message; } template void RETURN::add_message(std::string _message) { message += _message; } template void RETURN::set_value(T _value) { value = _value; } template T RETURN::get_value() const { return value; } template bool RETURN::is_error() const { return rc == error; } template std::string RETURN::get_message() const { return message; } template RETURN& RETURN::operator=(const RETURN &_other){ if (this == &_other) return *this; value = _other.value; rc = _other.rc; message = _other.message; return *this; } #include "stdafx.h" #include "header.h" #include "Function.h" double add(double *args) { return args[0] + args[1]; } double sin(double *args) { return std::sin(*args); } double subtract(double *args) { return args[0] - args[1]; } int main() { { Tree t; t.add_function("+", 2, &add); t.add_function("-", 2, &subtract); t.add_constant(1); t.add_constant(2); t.add_constant(3); Tree t2; t2.add_function("sin", 1, &sin); t2.add_constant(4); Tree res; res = t + t2; } std::cin.get(); return 0; }