所以我有一个项目,我必须为用户创建一个测试模式,检查我的复制构造函数和二进制搜索树的析构函数。我通过将二进制搜索树按值传递给类似testAdds
的函数来执行此操作,该函数在内部调用复制构造函数,并在函数返回后隐式调用析构函数,从而确保它们都能正常工作。我遇到的问题是,在函数返回后调用析构函数时,它最终会删除我原来的二进制搜索树。我不知道为什么会发生这种情况,即使我按值而不是通过引用传递它。有人可以帮我理解为什么会发生这种情况以及如何解决这个问题?任何和所有的帮助表示赞赏!
这是我的代码:
//Executive is the class where I call the test methods (in switch case 6)
#include<fstream>
#include "Executive.h"
Executive::Executive(char* filename) : choice(0), cont(true)
{
copycheck = false;
file = filename;
in.open(file);
string line;
while(getline(in, line))
{
string a;
string j;
string p;
int i=0;
for(char&c : line)
{
if(c==',') i++;
else if(c==' ') continue;
else if(i==0) a += c;
else if(i==1) p += c;
else if(i==2) j += c;
}
Pokemon p1(a, stoi(p), j);
if(!bst.add(p1))
{
cout<<"Could not add "<<a<<endl;
}
}
}
ofstream out;
void write(Pokemon& p)
{
out<<p.getAname()<<","<<p.getPokenum()<<","<<p.getJname()<<endl;
}
void Executive::run()
{
try
{
while(cont)
{
cout<<"What do you want to do with the Pokedex?"<<endl;
cout<<"1) Search"<<endl;
cout<<"2) Save"<<endl;
cout<<"3) Copy"<<endl;
cout<<"4) Add"<<endl;
cout<<"5) Remove"<<endl;
cout<<"6) Test"<<endl;
cout<<"7) Quit"<<endl;
cin>>choice;
while(choice<1 || choice>7)
{
cout<<"Invalid choice. Try again"<<endl;
cin>>choice;
}
switch(choice)
{
case 1:
{
string name;
cout<<"\nEnter the Pokemon's American name: ";
cin>>name;
if(bst.contains(name))
{
Pokemon temp = bst.getEntry(name);
cout<<"Japanese Name: "<<temp.getJname()<<endl;
cout<<"Pokedex Number: "<<temp.getPokenum()<<'\n'<<endl;
}
else
{
cout<<name<<" is not in the pokedex\n"<<endl;
}
break;
}
case 2:
{
string outfile;
string order;
if(copycheck)
{
cout<<"\nWhich pokedex do you want to save?"<<endl;
cout<<"1) Original"<<endl;
cout<<"2) Copy"<<endl;
cin>>choice;
while(choice<1 || choice>2)
{
cout<<"Invalid choice. Try again"<<endl;
cin>>choice;
}
}
else choice=1;
cout<<"Enter name for output file: ";
cin>>outfile;
out.open(outfile);
cout<<"Enter order of traversal:"<<endl;
cout<<"1) pre"<<endl;
cout<<"2) in"<<endl;
cout<<"3) post"<<endl;
int ochoice;
cin>>ochoice;
while(ochoice<1 || ochoice>3)
{
cout<<"Invalid choice. Try again"<<endl;
cin>>ochoice;
}
if(ochoice==1)
{
if(choice==1) bst.preorderTraverse(write);
else bstcopy.inorderTraverse(write);
}
else if(ochoice==2)
{
if(choice==1) bst.inorderTraverse(write);
else bstcopy.inorderTraverse(write);
}
else
{
if(choice==1) bst.postorderTraverse(write);
else bstcopy.postorderTraverse(write);
}
out.close();
cout<<"An output file with the name "<<outfile<<" has been created!\n"<<endl;
break;
}
case 3:
{
bstcopy = bst;
copycheck = true;
cout<<"\nA copy of the pokedex has been created for editing\n"<<endl;
break;
}
case 4:
{
if(copycheck)
{
string a, j;
int n;
cout<<"\nEnter pokemon's American name: ";
cin>>a;
a[0] = toupper(a[0]);
for(int i=1; i<a.length(); i++)
{
a[i] = tolower(a[i]);
}
cout<<"Enter pokemon's Japanese name: ";
cin>>j;
j[0] = toupper(j[0]);
for(int i=1; i<j.length(); i++)
{
j[i] = tolower(j[i]);
}
cout<<"Enter pokedex number: ";
cin>>n;
Pokemon p1(a, n, j);
if(!bstcopy.add(p1))
{
cout<<"Could not add "<<a<<'\n'<<endl;
}
else
{
cout<<a<<" has been successfully added to the pokedex\n"<<endl;
}
}
else
{
cout<<"\nYou need to create a copy before editing the pokedex!\n"<<endl;
}
break;
}
case 5:
{
if(copycheck)
{
string a;
cout<<"\nEnter pokemon's American name: ";
cin>>a;
if(bstcopy.remove(a))
{
cout<<a<<" was successfully removed from the pokedex\n"<<endl;
}
else
{
cout<<a<<" is not in the pokedex!\n"<<endl;
}
}
else
{
cout<<"\nYou need to create a copy before editing the pokedex!\n"<<endl;
}
break;
}
case 6:
{
cout<<"\nWhich test would you like to run?"<<endl;
cout<<"1) Test adding to a deep copy"<<endl;
cout<<"2) Test removing from a deep copy"<<endl;
cout<<"3) Test writing to file from a deep copy"<<endl;
cin>>choice;
while(choice<1 || choice>3)
{
cout<<"Invalid choice. Try again"<<endl;
cin>>choice;
}
if(choice == 1) t.testAdds(bst);
else if(choice == 2) t.testRemoves(bst);
else t.testWriteToFile(bst);
cout<<endl;
break;
}
default:
cont = false;
}
}
cout<<"\nThanks for using the Pokedex!\n"<<endl;
}
catch(NotFoundException& e)
{
cout<<e.what()<<endl;
}
}
//Test is the class where the test methods are defined
#include "Test.h"
ofstream fout;
void writetofile(Pokemon& p)
{
fout<<p.getAname()<<","<<p.getPokenum()<<","<<p.getJname()<<endl;
}
void display(Pokemon& p)
{
cout<<p.getAname()<<","<<p.getPokenum()<<","<<p.getJname()<<endl;
}
void Test::testAdds(BinarySearchTree<Pokemon, string> bstc)
{
string a, j;
int n;
cout<<"Enter pokemon's American name: ";
cin>>a;
a[0] = toupper(a[0]);
for(int i=1; i<a.length(); i++)
{
a[i] = tolower(a[i]);
}
cout<<"Enter pokemon's Japanese name: ";
cin>>j;
j[0] = toupper(j[0]);
for(int i=1; i<j.length(); i++)
{
j[i] = tolower(j[i]);
}
cout<<"Enter pokedex number: ";
cin>>n;
Pokemon p1(a, n, j);
if(!bstc.add(p1))
{
cout<<"Could not add "<<a<<endl;
}
else
{
bstc.inorderTraverse(display);
}
//bst.~BinarySearchTree();
}
void Test::testRemoves(BinarySearchTree<Pokemon, string> bstc)
{
string a;
cout<<"Enter pokemon's American name: ";
cin>>a;
if(bstc.remove(a))
{
bstc.inorderTraverse(display);
}
else
{
cout<<a<<" is not in the pokedex!"<<endl;
}
//bst.~BinarySearchTree();
}
void Test::testWriteToFile(BinarySearchTree<Pokemon, string> bstc)
{
string outfile;
cout<<"Enter name for output file: ";
cin>>outfile;
fout.open(outfile);
bstc.inorderTraverse(writetofile);
fout.close();
cout<<"An output file with the name "<<outfile<<" has been created!"<<endl;
//bst.~BinarySearchTree();
}
//Here's my Binary Search Tree file. I implement the copy constructor using a private recursive function called "copy" and overlaoding the = operator
// Subsetted from:
// Created by Frank M. Carrano and Tim Henry.
// Copyright (c) 2013 __Pearson Education__. All rights reserved.
/** @file BinarySearchTree.cpp */
#include <iostream>
#include "BinarySearchTree.h"
// PRIVATE HELPER METHODS - IMPLEMENT THESE
template<typename ItemType, typename KeyType>
void BinarySearchTree<ItemType, KeyType>::destroyTree(BinaryNode<ItemType>* subTreePtr)
{
if(subTreePtr != nullptr)
{
if(subTreePtr->getLeftChildPtr() != nullptr)
{
destroyTree(subTreePtr->getLeftChildPtr());
}
if(subTreePtr->getRightChildPtr() != nullptr)
{
destroyTree(subTreePtr->getRightChildPtr());
}
delete subTreePtr;
}
}
template<typename ItemType, typename KeyType>
BinaryNode<ItemType>* BinarySearchTree<ItemType,KeyType>::insertInorder(BinaryNode<ItemType>* subTreePtr, BinaryNode<ItemType>* newNodePtr)
{
if(newNodePtr->getItem() < subTreePtr->getItem())
{
if(subTreePtr->getLeftChildPtr() == nullptr)
{
subTreePtr->setLeftChildPtr(newNodePtr);
return nullptr;
}
else
{
return insertInorder(subTreePtr->getLeftChildPtr(), newNodePtr);
}
}
if(newNodePtr->getItem() > subTreePtr->getItem())
{
if(subTreePtr->getRightChildPtr() == nullptr)
{
subTreePtr->setRightChildPtr(newNodePtr);
return nullptr;
}
else
{
return insertInorder(subTreePtr->getRightChildPtr(), newNodePtr);
}
}
return newNodePtr;
}
template<typename ItemType, typename KeyType>
BinaryNode<ItemType>* BinarySearchTree<ItemType, KeyType>::findNode(BinaryNode<ItemType>* subTreePtr, const KeyType& target) const
{
if(subTreePtr != nullptr)
{
if(subTreePtr->getItem() > target)
{
return findNode(subTreePtr->getLeftChildPtr(), target);
}
if(subTreePtr->getItem() < target)
{
return findNode(subTreePtr->getRightChildPtr(), target);
}
return subTreePtr;
}
return nullptr;
}
template<typename ItemType, typename KeyType>
BinaryNode<ItemType>* BinarySearchTree<ItemType, KeyType>::recRemove(BinaryNode<ItemType>* root, ItemType& itemkey)
{
if(root == nullptr)
{
return nullptr;
}
else if(root->getItem()>itemkey)
{
root->setLeftChildPtr(recRemove(root->getLeftChildPtr(), itemkey));
}
else if(root->getItem()<itemkey)
{
root->setRightChildPtr(recRemove(root->getRightChildPtr(), itemkey));
}
else
{
if(root->isLeaf())
{
delete root;
}
else if(root->getLeftChildPtr() == nullptr)
{
BinaryNode<ItemType>* temp = root;
root = root->getRightChildPtr();
delete temp;
}
else if(root->getRightChildPtr() == nullptr)
{
BinaryNode<ItemType>* temp = root;
root = root->getLeftChildPtr();
delete temp;
}
else
{
BinaryNode<ItemType>* b = greatest(root->getLeftChildPtr());
ItemType item = b->getItem();
root->setItem(item);
root->setLeftChildPtr(recRemove(root->getLeftChildPtr(), item));
}
}
return root;
}
template<typename ItemType, typename KeyType>
void BinarySearchTree<ItemType, KeyType>::recPre(void visit(ItemType&), BinaryNode<ItemType>* subTreePtr) const
{
if(subTreePtr != nullptr)
{
ItemType temp = subTreePtr->getItem();
visit(temp);
recPre(visit, subTreePtr->getLeftChildPtr());
recPre(visit, subTreePtr->getRightChildPtr());
}
}
template<typename ItemType, typename KeyType>
void BinarySearchTree<ItemType, KeyType>::recIn(void visit(ItemType&), BinaryNode<ItemType>* subTreePtr) const
{
if(subTreePtr != nullptr)
{
recIn(visit, subTreePtr->getLeftChildPtr());
ItemType temp = subTreePtr->getItem();
visit(temp);
recIn(visit, subTreePtr->getRightChildPtr());
}
}
template<typename ItemType, typename KeyType>
void BinarySearchTree<ItemType, KeyType>::recPost(void visit(ItemType&), BinaryNode<ItemType>* subTreePtr) const
{
if(subTreePtr != nullptr)
{
recPost(visit, subTreePtr->getLeftChildPtr());
recPost(visit, subTreePtr->getRightChildPtr());
ItemType temp = subTreePtr->getItem();
visit(temp);
}
}
template<typename ItemType, typename KeyType>
BinaryNode<ItemType>* BinarySearchTree<ItemType, KeyType>::copy(BinaryNode<ItemType>* optr)
{
if(optr != nullptr)
{
BinaryNode<ItemType>* newNode = new BinaryNode<ItemType>(optr->getItem());
newNode->setLeftChildPtr(copy(optr->getLeftChildPtr()));
newNode->setRightChildPtr(copy(optr->getRightChildPtr()));
return newNode;
}
return nullptr;
}
template<typename ItemType, typename KeyType>
BinaryNode<ItemType>* BinarySearchTree<ItemType, KeyType>::greatest(BinaryNode<ItemType>* ptr)
{
if(ptr!=nullptr && ptr->getRightChildPtr()!=nullptr)
{
return greatest(ptr->getRightChildPtr());
}
if(ptr!=nullptr && ptr->getRightChildPtr()==nullptr)
{
return ptr;
}
return nullptr;
}
//////////////////////////////////////////////////////////////
// PUBLIC METHODS BEGIN HERE
//////////////////////////////////////////////////////////////
template<typename ItemType, typename KeyType>
BinarySearchTree<ItemType, KeyType>::BinarySearchTree() : rootPtr(nullptr)
{
}
template<typename ItemType, typename KeyType>
BinarySearchTree<ItemType, KeyType>::~BinarySearchTree()
{
this->destroyTree(rootPtr); // Call inherited method
} // end destructor
//////////////////////////////////////////////////////////////
// Public BinaryTreeInterface Methods Section - IMPLEMENT THESE
//////////////////////////////////////////////////////////////
template<typename ItemType, typename KeyType>
void BinarySearchTree<ItemType, KeyType>::operator=(BinarySearchTree<ItemType, KeyType>& bst)
{
this->rootPtr = copy(bst.rootPtr);
}
template<typename ItemType, typename KeyType>
bool BinarySearchTree<ItemType, KeyType>::add(const ItemType& newData)
{
BinaryNode<ItemType>* newNode = new BinaryNode<ItemType>(newData);
if(rootPtr == nullptr)
{
rootPtr = newNode;
return true;
}
if(insertInorder(rootPtr, newNode) == nullptr)
{
return true;
}
return false;
}
template<typename ItemType, typename KeyType>
bool BinarySearchTree<ItemType, KeyType>::remove(const KeyType& key)
{
if(contains(key))
{
KeyType a = key;
ItemType item = getEntry(a);
rootPtr = recRemove(rootPtr, item);
return true;
}
return false;
}
template<typename ItemType, typename KeyType>
ItemType BinarySearchTree<ItemType, KeyType>::getEntry(const KeyType& aKey) const throw(NotFoundException)
{
BinaryNode<ItemType>* entry = findNode(rootPtr, aKey);
if(entry != nullptr)
{
return entry->getItem();
}
throw(NotFoundException("Node with given key doesn't exist"));
}
template<typename ItemType, typename KeyType>
bool BinarySearchTree<ItemType, KeyType>::contains(const KeyType& aKey) const
{
BinaryNode<ItemType>* entry = findNode(rootPtr, aKey);
if(entry != nullptr)
{
return true;
}
return false;
}
//////////////////////////////////////////////////////////////
// Public Traversals Section - IMPLEMENT THESE
//////////////////////////////////////////////////////////////
template<typename ItemType, typename KeyType>
void BinarySearchTree<ItemType, KeyType>::preorderTraverse(void visit(ItemType&)) const
{
recPre(visit, rootPtr);
}
template<typename ItemType, typename KeyType>
void BinarySearchTree<ItemType, KeyType>::inorderTraverse(void visit(ItemType&)) const
{
recIn(visit, rootPtr);
}
template<typename ItemType, typename KeyType>
void BinarySearchTree<ItemType, KeyType>::postorderTraverse(void visit(ItemType&)) const
{
recPost(visit, rootPtr);
}