#include "stdafx.h"
#include "CInterFace.h"
#include <iostream>
using namespace std;
int main()
{
{
CInterFace c_interFace;
while (c_interFace.iGetAndExecuteCommand() != -1)
{
cout << "_______________________" << endl;
}
}
return 0;
}
#pragma once
#include <string>
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 <iostream>
#include <vector>
#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<string>& vctrGetVariableVector();
int BuildTree(vector<string> &vctrLoadedTokens);
string toString();
double Evaluate(vector<int> &vctrLoadedVariables, int &iErrorCode);
private:
void AddIfNewVariable(string &sVariableName);
void DeleteIfWasVariable(string &sVariableName);
int BuildSubTree(CNode*& pcRootNode, vector<string> &vctrLoadedTokens);
int ValueForVariable(string sVarName, vector<int> &vctrLoadedVariables);
double CalculateSubtree(CNode *pcRootNode, vector<int> &vctrLoadedVariables, int &iErrorCode);
CNode *_root;
vector<string> _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<string>& CTree::vctrGetVariableVector()
{
return _variables;
}
int CTree::BuildTree(vector<string> &vctrLoadedTokens)
{
if (_root != nullptr)
{
delete _root;
_variables.clear();
_root = nullptr;
}
return BuildSubTree(_root, vctrLoadedTokens);
}
int CTree::BuildSubTree(CNode*& pcRootNode, vector<string> &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<int> &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<int> &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<int> &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 <iostream>
#include <string>
#include <vector>
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<string> vctr_loadedTokens;
private:
void vSplit(vector<string> &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<string> &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<int> 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;
}