#include "stdafx.h" #include "CInterFace.h" #include using namespace std; int main() { { CInterFace c_interFace; while (c_interFace.iGetAndExecuteCommand() != -1) { cout << "_______________________" << endl; } } return 0; } #pragma once #include using namespace std; #define S_UNDEFINED "undef" #define I_ERR_OK 0 #define I_ERR_VAR_WITH_INVALID_CHAR 1 #define S_ERR_VAR_WITH_INVALID_CHAR "Variable(s) with invalid char, loaded as: " class CNode { enum e_nodeType { op1arg, op2arg, value, variable }; friend class CTree; public: CNode(string sValue); CNode(CNode &cOther); ~CNode(); private: bool IsAnInteger(); bool IsOneArgOperator(); bool IsTwoArgsOperator(); bool IsVariable(); int SetTypeAndMaxChildren(); string toString(); string _value; CNode **_children; int _maxChildren; int _definedChildren; e_nodeType e_type; }; #include "stdafx.h" #include "CNode.h" CNode::CNode(string sValue) { _value = sValue; _definedChildren = 0; SetTypeAndMaxChildren(); if (_maxChildren > 0) { _children = new CNode*[_maxChildren]; } else { _children = nullptr; } } CNode::CNode(CNode &cOther) { _value = cOther._value; _maxChildren = cOther._maxChildren; e_type = cOther.e_type; if (_maxChildren > 0) { _children = new CNode*[_maxChildren]; for (_definedChildren = 0; _definedChildren < _maxChildren; _definedChildren++) { *(_children + _definedChildren) = new CNode(**(cOther._children + _definedChildren)); } } else { _children = nullptr; } } CNode::~CNode() { if (_children != nullptr) { for (int i = 0; i < _maxChildren; i++) { delete *(_children + i); } delete _children; _children = nullptr; } } bool CNode::IsAnInteger() { return (_value.find_first_not_of("0123456789") == string::npos); } bool CNode::IsOneArgOperator() { return (_value == "sin" || _value == "cos"); } bool CNode::IsTwoArgsOperator() { return (_value == "+" || _value == "-" || _value == "*" || _value == "/"); } bool CNode::IsVariable() { bool bIsVar = true; int i_size = _value.size(); for (int i = 0; i < i_size && bIsVar; i++) { char c_char = _value.at(i); if (c_char < 48 || c_char > 122 || (c_char > 57 && c_char < 65) || (c_char > 90 && c_char < 97)) { bIsVar = false; } } return bIsVar; } int CNode::SetTypeAndMaxChildren() { if (IsAnInteger()) { e_type = value; _maxChildren = 0; } else if (IsTwoArgsOperator()) { e_type = op2arg; _maxChildren = 2; } else if (IsOneArgOperator()) { e_type = op1arg; _maxChildren = 1; } else { e_type = variable; _maxChildren = 0; if (!IsVariable()) { _value = S_UNDEFINED; return I_ERR_VAR_WITH_INVALID_CHAR; } } return I_ERR_OK; } string CNode::toString() { string s_retString = _value; for (int i = 0; i < _maxChildren; i++) { s_retString += (" " + (*(_children + i))->toString()); } return s_retString; } #pragma once #include "CNode.h" #include #include #define S_DEF_VAL "1" #define S_OP_SIN "sin" #define S_OP_COS "cos" #define S_OP_ADD "+" #define S_OP_SUB "-" #define S_OP_MUL "*" #define S_OP_DIV "/" #define S_NOT_DEFINED_DEBUG_LOG "Not defined operation!" #define I_ERR_EMPTY_TREE 2 #define S_ERR_EMPTY_TREE "Tree is empty!" #define I_ERR_DIV_BY_ZERO 3 #define S_ERR_DIV_BY_ZERO "Dividing by zero!" #define I_ERR_INVALID_EXPRESSION 4 #define S_ERR_IVALID_EXPRESSION "Invalid expresion! Loaded:\n" class CTree { public: CTree(); CTree(CTree &cOther); ~CTree(); CTree operator +(CTree &other); void operator =(CTree &other); vector& vctrGetVariableVector(); int BuildTree(vector &vctrLoadedTokens); string toString(); double Evaluate(vector &vctrLoadedVariables, int &iErrorCode); private: void AddIfNewVariable(string &sVariableName); void DeleteIfWasVariable(string &sVariableName); int BuildSubTree(CNode*& pcRootNode, vector &vctrLoadedTokens); int ValueForVariable(string sVarName, vector &vctrLoadedVariables); double CalculateSubtree(CNode *pcRootNode, vector &vctrLoadedVariables, int &iErrorCode); CNode *_root; vector _variables; }; #include "stdafx.h" #include "CTree.h" CTree::CTree() { _root = nullptr; } CTree::CTree(CTree &cOther) { _variables = cOther._variables; _root = new CNode(*cOther._root); } CTree::~CTree() { if (_root != nullptr) { delete _root; _root = nullptr; } } CTree CTree::operator +(CTree &cOther) { CTree c_newTree; if (_root == nullptr) { if (cOther._root != nullptr) { c_newTree = cOther; c_newTree._variables = cOther._variables; } } else if (cOther._root != nullptr) { c_newTree = *this; CNode* pc_currentNode = c_newTree._root; if (pc_currentNode->_children == nullptr) { delete c_newTree._root; c_newTree._root = new CNode(*cOther._root);; } else { while ((*pc_currentNode->_children)->_maxChildren > 0) { pc_currentNode = *pc_currentNode->_children; } c_newTree.DeleteIfWasVariable((*(pc_currentNode->_children))->_value); delete *(pc_currentNode->_children); *(pc_currentNode->_children) = new CNode(*cOther._root);; } for (int i = 0; i < cOther._variables.size(); i++) { c_newTree.AddIfNewVariable(cOther._variables.at(i)); } } return c_newTree; } void CTree::operator =(CTree &cOther) { _variables = cOther._variables; if (_root != nullptr) { delete _root; } _root = new CNode(*cOther._root); } vector& CTree::vctrGetVariableVector() { return _variables; } int CTree::BuildTree(vector &vctrLoadedTokens) { if (_root != nullptr) { delete _root; _variables.clear(); _root = nullptr; } return BuildSubTree(_root, vctrLoadedTokens); } int CTree::BuildSubTree(CNode*& pcRootNode, vector &vctrLoadedTokens) { int i_errorCode = I_ERR_OK; if (!vctrLoadedTokens.empty()) { pcRootNode = new CNode(vctrLoadedTokens.at(0)); if (pcRootNode->e_type == CNode::variable) { AddIfNewVariable(pcRootNode->_value); } vctrLoadedTokens.erase(vctrLoadedTokens.begin()); } else { i_errorCode = I_ERR_INVALID_EXPRESSION; pcRootNode = new CNode(S_DEF_VAL); } for (; pcRootNode->_definedChildren < pcRootNode->_maxChildren; pcRootNode->_definedChildren++) { i_errorCode = BuildSubTree(*(pcRootNode->_children + pcRootNode->_definedChildren), vctrLoadedTokens); } return i_errorCode; } void CTree::AddIfNewVariable(string &sVariableName) { bool bFound = false; int i_varCount = _variables.size(); for (int i = 0; i < i_varCount && !bFound; i++) { if (_variables.at(i) == sVariableName) { bFound = true; } } if (!bFound) { _variables.push_back(sVariableName); } } void CTree::DeleteIfWasVariable(string &sVariableName) { int i_varCount = _variables.size(); bool b_found = false; for (int i = 0; i < i_varCount && !b_found; i++) { if (_variables.at(i) == sVariableName) { _variables.erase(_variables.begin() + i); b_found = true; } } } string CTree::toString() { if (_root != nullptr) { return _root->toString(); } } double CTree::Evaluate(vector &vctrLoadedVariables, int &iErrorCode) { if (_root == nullptr) { return iErrorCode = I_ERR_EMPTY_TREE; } else { iErrorCode = I_ERR_OK; return CalculateSubtree(_root, vctrLoadedVariables, iErrorCode); } } double CTree::CalculateSubtree(CNode *pcRootNode, vector &vctrLoadedVariables, int &iErrorCode) { if (iErrorCode == I_ERR_OK) { switch (pcRootNode->e_type) { case CNode::value: return stoi(pcRootNode->_value); case CNode::variable: return ValueForVariable(pcRootNode->_value, vctrLoadedVariables); case CNode::op1arg: if (pcRootNode->_value == S_OP_SIN) { return sin(CalculateSubtree(*pcRootNode->_children, vctrLoadedVariables, iErrorCode)); } else if (pcRootNode->_value == S_OP_COS) { return cos(CalculateSubtree(*pcRootNode->_children, vctrLoadedVariables, iErrorCode)); } case CNode::op2arg: if (pcRootNode->_value == S_OP_ADD) { return CalculateSubtree(*pcRootNode->_children, vctrLoadedVariables, iErrorCode) + CalculateSubtree(*(pcRootNode->_children + 1), vctrLoadedVariables, iErrorCode); } else if (pcRootNode->_value == S_OP_SUB) { return CalculateSubtree(*pcRootNode->_children, vctrLoadedVariables, iErrorCode) - CalculateSubtree(*(pcRootNode->_children + 1), vctrLoadedVariables, iErrorCode); } else if (pcRootNode->_value == S_OP_MUL) { return CalculateSubtree(*pcRootNode->_children, vctrLoadedVariables, iErrorCode) * CalculateSubtree(*(pcRootNode->_children + 1), vctrLoadedVariables, iErrorCode); } else if (pcRootNode->_value == S_OP_DIV) { int i_divider = CalculateSubtree(*(pcRootNode->_children + 1), vctrLoadedVariables, iErrorCode); if (i_divider == 0) { iErrorCode = I_ERR_DIV_BY_ZERO; return stod(S_DEF_VAL); } else return CalculateSubtree(*pcRootNode->_children, vctrLoadedVariables, iErrorCode) / i_divider; } break; } } else { return stod(S_DEF_VAL); } } int CTree::ValueForVariable(string sVarName, vector &vctrLoadedVariables) { bool b_isFound = false; int i_varCount = (vctrLoadedVariables.size() < _variables.size()) ? vctrLoadedVariables.size() : _variables.size(); int i_value = 0; for (int i = 0; i < i_varCount && !b_isFound; i++) { if (_variables.at(i) == sVarName) { i_value = vctrLoadedVariables.at(i); b_isFound = true; } } return i_value; } #pragma once #include "CTree.h" #include #include #include using namespace std; #define S_CMD_ENTER "enter" #define S_CMD_VARS "vars" #define S_CMD_PRINT "print" #define S_CMD_COMP "comp" #define S_CMD_JOIN "join" #define S_CMD_EXIT "exit" #define S_RESULT "result: " #define I_ERR_INVALID_ARGUMENT 5 #define S_ERR_INVALID_ARGUMENT "Invalid argument!" #define I_ERR_NOT_ENOUGH_ARGUMENTS 6 #define S_ERR_NOT_ENOUGH_ARGUMENTS "Not enough arguments!" #define I_ERR_TOO_MANY_ARGUMENTS 7 #define S_ERR_TOO_MANY_ARGUMENTS "Too many arguments!" #define I_ERR_UNRECOGNISED_COMMAND 8 #define S_ERR_UNRECOGNISED_COMMAND "Unrecognised command!" #define I_END_PROGRAM -1 class CInterFace { public: CInterFace(); ~CInterFace(); int iGetAndExecuteCommand(); int iProceedJoin(); vector vctr_loadedTokens; private: void vSplit(vector &result, string str, char delim); int iProceedEnter(); int iProceedVars(); int iProceedPrint(); int iProceedComp(); int iProceedExit(); bool bIsAnPositiveInteger(string sStr); CTree c_tree; }; #include "stdafx.h" #include "CInterFace.h" CInterFace::CInterFace() { } CInterFace::~CInterFace() { } int CInterFace::iGetAndExecuteCommand() { cin.clear(); string s_Line; getline(cin, s_Line); vSplit(vctr_loadedTokens, s_Line, ' '); int i_errorCode; string s_command = vctr_loadedTokens.at(0); vctr_loadedTokens.erase(vctr_loadedTokens.begin()); if (s_command == S_CMD_ENTER) { i_errorCode = iProceedEnter(); } else if (s_command == S_CMD_VARS) { i_errorCode = iProceedVars(); } else if (s_command == S_CMD_PRINT) { i_errorCode = iProceedPrint(); } else if (s_command == S_CMD_COMP) { i_errorCode = iProceedComp(); } else if (s_command == S_CMD_JOIN) { i_errorCode = iProceedJoin(); } else if (s_command == S_CMD_EXIT) { i_errorCode = iProceedExit(); } else { i_errorCode = I_ERR_UNRECOGNISED_COMMAND; } switch (i_errorCode) { case I_ERR_VAR_WITH_INVALID_CHAR: cout << S_ERR_VAR_WITH_INVALID_CHAR << S_UNDEFINED << endl; break; case I_ERR_EMPTY_TREE: cout << S_ERR_EMPTY_TREE << endl; break; case I_ERR_DIV_BY_ZERO: cout << S_ERR_DIV_BY_ZERO << endl; break; case I_ERR_INVALID_EXPRESSION: cout << S_ERR_IVALID_EXPRESSION << c_tree.toString() << endl; break; case I_ERR_INVALID_ARGUMENT: cout << S_ERR_INVALID_ARGUMENT << endl; break; case I_ERR_NOT_ENOUGH_ARGUMENTS: cout << S_ERR_NOT_ENOUGH_ARGUMENTS << endl; break; case I_ERR_TOO_MANY_ARGUMENTS: cout << S_ERR_TOO_MANY_ARGUMENTS << endl; break; case I_ERR_UNRECOGNISED_COMMAND: cout << S_ERR_UNRECOGNISED_COMMAND << endl; break; } return i_errorCode; } void CInterFace::vSplit(vector &result, string str, char delim) { string tmp = ""; result.clear(); for (string::iterator i = str.begin(); i < str.end(); ++i) { if ((const char)*i != delim && i != str.end()) { tmp += *i; } else { if (tmp != "") { result.push_back(tmp); } tmp = ""; } } if (tmp != "") { result.push_back(tmp); } } int CInterFace::iProceedEnter() { return c_tree.BuildTree(vctr_loadedTokens); } int CInterFace::iProceedVars() { if (vctr_loadedTokens.empty()) { int i_varCount = c_tree.vctrGetVariableVector().size(); for (int i = 0; i < i_varCount; i++) { cout << c_tree.vctrGetVariableVector().at(i) << "\t"; } cout << endl; return I_ERR_OK; } else { return I_ERR_TOO_MANY_ARGUMENTS; } } int CInterFace::iProceedPrint() { if (vctr_loadedTokens.empty()) { cout << c_tree.toString() << endl; return I_ERR_OK; } else { return I_ERR_TOO_MANY_ARGUMENTS; } } int CInterFace::iProceedComp() { int i_varsCount = c_tree.vctrGetVariableVector().size(); int i_tokensCount = vctr_loadedTokens.size(); if (i_tokensCount > i_varsCount) { return I_ERR_TOO_MANY_ARGUMENTS; } if (i_tokensCount < i_varsCount) { return I_ERR_NOT_ENOUGH_ARGUMENTS; } bool b_argsCorrect = true; vector vctr_loadedVars; string sActToken; for (int i = 0; i < i_tokensCount && b_argsCorrect; i++) { sActToken = vctr_loadedTokens.at(i); if (bIsAnPositiveInteger(sActToken)) { vctr_loadedVars.emplace_back(stoi(sActToken)); } else { b_argsCorrect = false; } } if (!b_argsCorrect) { return I_ERR_INVALID_ARGUMENT; } int i_errCode = I_ERR_OK; double d_potResult = c_tree.Evaluate(vctr_loadedVars, i_errCode); if (i_errCode == I_ERR_OK) { cout << S_RESULT << d_potResult << endl; } return i_errCode; } int CInterFace::iProceedJoin() { CTree newTree; int i_errorCode = newTree.BuildTree(vctr_loadedTokens); c_tree = c_tree + newTree; return i_errorCode; } int CInterFace::iProceedExit() { return I_END_PROGRAM; } bool CInterFace::bIsAnPositiveInteger(string sStr) { return (sStr.find_first_not_of("0123456789") == std::string::npos) && stoi(sStr) > 0; }