I am trying to figure out how to create a tree in C++. I have tried debugging this for hours and I thought it was time I got another set of eyes on it. My question is if my treeNodeClass looks correct. Right now I am getting a stack explosion because I’m double removing items from my node. The tree itself will be parsing a simple xml file. Here is my code.
#include "treeNodeClass.h"
TreeNodeClass::TreeNodeClass()
{
cout << "TREENODECLASS::TREENODECLASS()" << endl;
attributes.clear();
children.clear();
data = "";
height = 0;
parent = NULL;
tag = "";
cout << "EXIT TREENODECLASS::TREENODECLASS()" << endl;
}
TreeNodeClass::TreeNodeClass(const TreeNodeClass& other)
{
cout << "TREENODECLASS::TREENODECLASS(const other)" << endl;
parent = NULL;
CopyIntoMe(other);
cout << "EXIT TREENODECLASS::TREENODECLASS(const other)" << endl;
}
TreeNodeClass::~TreeNodeClass()
{
cout << "TREENODECLASS::~TREENODECLASS()" << endl;
if(parent)
delete parent;
parent = NULL;
children.clear();
attributes.clear();
cout << "EXIT TREENODECLASS::~TREENODECLASS()" << endl;
}
void TreeNodeClass::CreateAttrib(string root, string val)
{
string attrib = root + "=" + val;
attributes.push_back(attrib);
}
void TreeNodeClass::CreateTag(string data, string name)
{
tag = name;
this->data = data;
}
list<string> TreeNodeClass::ReturnAttrib()
{
return this->attributes;
}
string TreeNodeClass::ReturnTag(string tag)
{
string retTag = "";
if(this->tag == tag)
retTag = this->tag;
return retTag;
}
void TreeNodeClass::AddChildren(TreeNodeClass* c)
{
if(c != NULL)
children.push_back(c);
}
TreeNodeClass& TreeNodeClass::operator=(const TreeNodeClass& other)
{
cout << "TREENODECLASS& TREENODECLASS OPERATOR = " << endl;
if(&other != this)
{
if(parent)
delete parent;
parent = NULL;
attributes.clear();
children.clear();
CopyIntoMe(other);
}
return *this;
}
void TreeNodeClass::CopyIntoMe(const TreeNodeClass& other)
{
cout << "Copy into me" << endl;
tag = other.tag;
data = other.data;
attributes = other.attributes;
children = other.children;
parent = new TreeNodeClass;
parent = other.parent;
height = other.height;
}
void TreeNodeClass::AddParent(TreeNodeClass* p)
{
if(p)
{
parent = new TreeNodeClass;
parent = p;
}
}
std::vector< TreeNodeClass* > TreeNodeClass::ReturnChildren()
{
return children;
}
ostream& operator<<(ostream& out, const TreeNodeClass& treeNode)
{
out << "NODE: " << treeNode.tag << " " << treeNode.data << endl;
out << "CHILDREN: " << treeNode.children.size() << endl;
out << "HEIGHT: " << treeNode.height << endl;
out << "Attributes: ";
for(list<string>::const_iterator iter = treeNode.attributes.begin(); iter != treeNode.attributes.end(); iter++)
{
out << *iter << " ";
}
out << endl;
}
void TreeNodeClass::SetHeight(int h)
{
height = h;
}
/*void function(TreeNodeClass* node)
{
cout << node << " " << *node << endl;
}
TreeNodeClass* function2(TreeNodeClass* node)
{
return node;
}
int main()
{
cout << "STARTING PROGRAM" << endl;
cout << "CREATING A TREE NODE CLASS " << endl;
TreeNodeClass* newNode;
TreeNodeClass* tempNode;
list<string> attribs;
newNode = new TreeNodeClass;
tempNode = new TreeNodeClass;
newNode->SetHeight(10);
cout << *tempNode << " " << *newNode << endl;
tempNode->SetHeight(20);
cout << *tempNode << "\n " << *newNode << endl;
cout << "Setting equal " << endl;
*tempNode = *newNode;
cout << *tempNode << " " << *newNode << endl;
tempNode->SetHeight(40);
cout << *tempNode << " " << *newNode << endl;
tempNode->AddChildren(newNode);
newNode->AddParent(tempNode);
cout << *tempNode << "\n " << *newNode << endl;
return 0;
}
*/
And I’m trying to use this code on a simple state machine. I basically set up a vector of lists to return the states. This is what I believe is giving me a majority of my errors. I’ve been staring at this as well for a while, but I’m kind of lost.The machine will create the tree (supposedly). When the state machine finishes (state 10) it returns and the calling function will just make another call to yylex(). Thanks for the help so far!
TreeNodeClass* ProcessTree(TokenT token, vector <list <stateAssoc> >& vecTree, int depth)
{
int state = 1; //Assume this is a new record.
bool noState = false;
bool update = true;
int dex = 0;
string root, value, data, tag;
TreeNodeClass* treeNode;
treeNode = new TreeNodeClass; //Assume a new node per state machine visit.
while(state != 10)
{
switch(state)
{
case 1: dex = 1;
break;
case 2: state = 3;
noState = true;
root = yylval;
break;
case 3: state = 4;
noState = true;
break;
case 4: dex = 3;
value = yylval;
//cout << value << endl;
treeNode->CreateAttrib(root, value);
break;
case 5: dex = 2;
data = yylval;
//cout << 5 << " " << yylval << " " << token << endl;
//If its data store as data; if tag its a start tag.
break;
case 6: dex = 4;
//cout << token << " " << yylval << endl;
break;
case 7: state = 9;
noState = true;
tag = yylval;
//cout << tag << token << endl;
if(data != "" and data != "authors")
treeNode->CreateTag(data, tag);
break;
case 8: {
TreeNodeClass* childNode = new TreeNodeClass;
childNode = ProcessTree(token, vecTree, depth+1);
cout << "BEFORE PARENT" << endl;
childNode->AddParent(treeNode);
childNode->SetHeight(depth);
treeNode->AddChildren(childNode);
delete childNode;
childNode = NULL;
}
token = TokenT(yylex()); //Get a new token to process.
dex = 5;
break;
case 9: state = 10;
noState = true;
update = false;
break;
case 10: noState = true;
update = false;
break;
default: cout << "Error " << endl;
cout << state << endl;
cin.get();
break;
}
if(!noState)
state = FindMatch(vecTree[dex], token);
else
noState = false;
if(update)
token = TokenT(yylex());
else
update = true;
}
return treeNode;
}
1.A children shouldn`t delete a parent:
2.Containers will not delete a pointer — you should take it in mind always. Easy way to delete, for example:
But best way — not use native pointers and use some smart pointers or shared pointers.
3.Main function do not delete pointers
tempNodeandnewNode.4.If you’ll use native pointers, you should recursively create and copy each children. In other way you’ll catch memory leak.
5.Example of method
CopyIntoMe: