My teacher asked to write a templete class List(just like in the STL)
My code compile but it will crash but I CAN`T find why, can anyone try to help me?
I think maybe there is problem with the constructor with two parameters?
-----Main.cpp------
#include "Liste.h"
#include <iostream>
int main()
{
Liste<int> l ;
int x = 5 ;
int y = 6 ;
int z = 7 ;
l.insert_first(y) ;
l.insert_first(x) ;
l.insert_last(z) ;
std::cout << l << std::endl ;
}
-----Liste.h------
#pragma once
#include <stdio.h>
#include <iostream>
#include "NoeudListe.h"
template <class T> class Liste
{
private:
NoeudListe<T>* tete;
NoeudListe<T>* fin;
public:
Liste()
{
tete = new NoeudListe<T>(NULL,fin,NULL); //<-----I think the problem lies here beacause the val can`t be NULL? But I tried 0, still not work...
fin = new NoeudListe<T>(tete,NULL,NULL);
}
void insert_after (T& val, NoeudListe<T>* location)
{
NoeudListe<T>* local = new NoeudListe<T>(location,location->getNext(),val);
(*(location->getNext())).setPrev(local);
location->setNext(local);
}
void insert_first(T& val)
{
insert_after (val, tete);
}
void insert_last(T& val)
{
insert_after (val, fin->getPrev());
}
friend std::ostream& operator << (std::ostream& os,const Liste<T>& location)
{
NoeudListe<T>* local=(location.tete)->getNext();
while( local->getVal() != NULL )
{
os<< local->getVal() << "\n";
local=local->getNext();
}
return os;
}
};
-----NoeudListe.h------
#pragma once
template <class T> class NoeudListe
{
private:
NoeudListe* prev;
NoeudListe* next;
T val;
public:
NoeudListe(NoeudListe* p, NoeudListe* n, const T& v)
{
prev = p;
next = n;
val = v;
}
void setNext(NoeudListe* n){ next = n;}
void setPrev(NoeudListe* p){ prev = p;}
void setVal(const T& v){ val = v;}
NoeudListe* getNext(){ return next;}
NoeudListe* getPrev(){ return prev;}
T getVal(){ return val;}
};
friend std::ostream& operator << (std::ostream& os,const Liste<T>& location)
{
NoeudListe<T>* local=(location.tete)->getNext();
while( local->getVal() != NULL )
{
os<< local->getVal() << "\n";
local=local->getNext();
}
return os;
}
You don't test here if local is NULL (why are you testing if local->getVal() is NULL ?), so you will get a segfault here.
Related
I am a beginner at c++ and I am coding a program that stores data into a BST template class the being another class called log_t that stores the variables, I am trying to use the inorder method from the BST class to reference a vector from main, to input the values into and be able to use it in the main class
my main class
int main(int argc, char* argv[])
{
BST<log_t> l;
string infilename = "";
string filePath = "data\\";
string files[1] = {
filePath + "MetData-31-3a.csv"
//filePath + "Jan20071toDec31abcdefghijklmnopq",
//filePath + "Jan20081toDec31abcdefghijklmnopq",
//filePath + "MetData_Jan01-2010-Jan01-2011-ALL"
};
/// checks if file can open
for (int i = 0; i < 1; i++) {
infilename = files[i];
ifstream infile(infilename);
if (!infile.is_open())
{
cout << "unable to read file" << files[i] << endl;
}
else
{
cout << "reading file" << files[i] << endl;
}
/* parse sensor data csv file */
string tmp;
getline(infile, tmp); // skip the first line
while (getline(infile, tmp))
{
// if successfully parsed then append into vector
log_t logline;
if (ParseLog(tmp, logline))
l.insert(logline);
}
}
cout << " end with reading file" << endl;
/* aggregate/filter logs */
Vector<log_t> vec;
l.inorder(vec);
/* prompt menu */
// this array stores all the menu option callback functions
void(*funs[])(const Vector<log_t> & vec) = { NULL, &option1, &option2, &option3, &option4, &option5,&option6 };
// keep printing menu in loop
while (true)
{
// prompt menu and ask user to select option
int choice = PromptMenu();
// check validity of choice
if (choice < 1 || choice > 6)
{
cout << "invalid choice" << endl;
}
else
{
cout << endl;
// call menu option handler
(funs[choice])(vec);
}
}
system("pause");
return -1;
}
my BST class
#include <string>
#include <iostream>
#include <stream>
#include <iomanip>
#include <stream>
#include "date.h"
#include "times.h"
#include "log_t.h"
#include "Vector.h"
using namespace std;
template <class T>
class BST {
private:
struct Node {
T num;
Node* left;
Node* right;
};
Node* root = NULL;
Node* insert(Node* node, T x);
Node* newnode(T num);
void removeprivate(T num, Node* parent);
T findsmallestprivate(Node* ptr);
void inorderprivate(Node* ptr, void (BST<T>::* FT)(T&), Vector<log_t>const& log);
void postorderprivate(Node* ptr, void (BST<T>::* FT)(T&));
void preorderprivate(Node* ptr, void (BST<T>::* FT)(T&));
//void inorderprivate(Node* ptr);
//void postorderprivate(Node* ptr);
//void preorderprivate(Node* ptr);
void removematch(Node* parent, Node* match, bool left);
public:
void insert(T num);
void remove(T num);
void removerootmatch();
T findsmallest();
void inorder(Vector<log_t>const& log);
void postorder();
void preorder();
void print(T& p) { cout << p << " "; };
};
template <class T>
void BST<T>::inorder(Vector<log_t>const& log) {
inorderprivate(root,print,log);
}
template <class T>
void BST<T>::inorderprivate(Node* ptr, void (BST<T>::* FT)(T&), Vector<log_t>const&
log) {
if (root != NULL)
{
if (ptr->left != NULL)
{
inorderprivate(ptr->left, FT);
}
(this->*FT)(log);
log.Append( ptr->num);
if (ptr->right != NULL)
{
inorderprivate(ptr->right, FT);
}
}
else
{
cout << "tree is empty";
}
}
my log_t class the T type
#pragma once
#ifndef LOG_T_H
#define LOG_T_H
#include <iostream>
#include <stream>
#include <string>
#include <algorithm>
#include <iomanip>
#include <stream>
#include "date.h"
#include "times.h"
#include "BST.h"
class log_t
{
public:
log_t();
log_t(log_t& log);
float gettemp();
float getwind();
float getsolar();
void setwind(float wind);
void setsolar(float rad);
void settemp(float temp);
Date date;
Times time;
private:
float wind_speed;
float solar_radiation;
float air_temperature;
};
log_t::log_t()
{
wind_speed = 0;
solar_radiation = 0;
air_temperature = 0;
}
log_t::log_t(log_t& log) {
wind_speed = log.wind_speed;
solar_radiation = log.solar_radiation;
air_temperature = log.air_temperature;
date.SetDate(log.date.GetDay(), log.date.GetMonth(), log.date.GetYear());
time.SetHour(log.time.GetHour());
time.SetMinute(log.time.GetMinute());
}
float log_t:: gettemp()
{
return air_temperature;
}
float log_t::getwind() {
return wind_speed;
}
float log_t::getsolar() {
return solar_radiation;
}
void log_t::setwind(float wind)
{
wind_speed = wind;
}
void log_t::setsolar(float rad)
{
solar_radiation = rad;
}
void log_t::settemp(float temp)
{
air_temperature = temp;
}
#endif // LOG_T_H
my vector class
#pragma once
#ifndef VECTOR_H
#define VECTOR_H
#include <iostream>
#include <stream>
#include <string>
template <class T>
class Vector
{
public:
Vector();
Vector(int capacity);
Vector(const Vector& vec);
Vector& operator=(const Vector& vec);
~Vector();
int GetSize() const;
void Expand();
T& GetLast();
void Append(const T& val);
T& operator[](int idx);
const T& operator[](int idx) const;
private:
T* elems;
int capacity;/** < int capacity, stores the size of the array */
int count;
void CopyFrom(const Vector& vec);
};
template <class T>
inline Vector<T>::Vector() : elems(nullptr), capacity(0), count(0)
{
}
template <class T>
inline Vector<T>::Vector(int capacity)
: elems(new T[capacity]()), capacity(capacity), count(0)
{
}
template <class T>
inline Vector<T>::Vector(const Vector& vec)
{
CopyFrom(vec);
}
template <class T>
inline Vector<T>& Vector<T>::operator=(const Vector& vec)
{
if (elems)
delete[] elems;
CopyFrom(vec);
return *this;
}
template <class T>
inline Vector<T>::~Vector()
{
if (elems)
delete[] elems;
}
template <class T>
inline int Vector<T>::GetSize() const
{
return count;
}
template <class T>
inline void Vector<T>::Expand()
{
++count;
if (count > capacity)
if (capacity)
capacity *= 2;
else
capacity = 4;
T* tmp = new T[capacity]();
for (int i = 0; i < count - 1; ++i)
tmp[i] = elems[I];
if (elems)
delete[] elems;
elems = tmp;
}
template <class T>
inline T& Vector<T>::GetLast()
{
return elems[count - 1];
}
template <class T>
inline void Vector<T>::Append(const T& oval)
{
Expand();
GetLast() = val;
}
template <class T>
inline T& Vector<T>::operator[](int idx)
{
return elems[idx];
}
template <class T>
inline const T& Vector<T>::operator[](int idx) const
{
return elems[idx];
}
template <class T>
inline void Vector<T>::CopyFrom(const Vector& vec)
{
elems = new T[vec.capacity]();
capacity = vec.capacity;
count = vec.count;
for (int i = 0; i < count; ++i)
elems[i] = vec.elems[i];
}
#endif //VECTOR_H
the errors that keep showing up are
Severity Code Description Project File Line Suppression State
Error (active) E0147 declaration is incompatible with "void BST::inorder(const Vector<> &log)" (declared at line 241 of "C:\Users\Frances\Documents\A2\A2\BST.h") A2 C:\Users\Frances\Documents\A2\A2\BST.h 241
Severity Code Description Project File Line Suppression State
Error C2065 'log_t': undeclared identifier A2 C:\Users\Frances\Documents\A2\A2\BST.h 33
Severity Code Description Project File Line Suppression State
Error C2923 'Vector': 'log_t' is not a valid template type argument for parameter 'T' A2 C:\Users\Frances\Documents\A2\A2\BST.h 33
could someone help me figure out what it is that's causing this or what I am doing wrong, I have been trying to find an answer for hours and haven't been successful thank you
So I'm getting a segmentation fault on my function here and I'm not sure how to correct it. Any clues as to how I would go about it?
I'm including my classes and then the function below to give an idea of what I have.
Thanks!
template <typename T>
class Element{
private:
Element *next_ = nullptr;
string name_ = "";
T color_ = T();
public:
Element()=default;
Element(string name, T d) : next_(nullptr), name_(name), color_(d){};
friend ostream& operator<<(ostream& out, Element& n){
out << n.name_ << ":" << n.color_;
return out;
}
friend class PAL<T>;
};
template<typename T>
class PAL{
private:
Element<T> *back_ = nullptr;
Element<T> *front_ = nullptr;
void print_list(ostream& out);
public:
PAL()=default;
PAL(Element<T> n) : back_(&n), front_(&n) {};
PAL(string n, T d);
PAL(const PAL&);
PAL& operator=(PAL);
~PAL();
void add(Element<T> &n);
void add(string name, T dat);
pair<Element<T>*, Element<T>*> find(string name);
pair<Element<T>*, Element<T>*> find(Element<T> &n);
void move_forward1(Element<T> &n);
void move_to_front(Element<T> &n);
void move_back1(Element<T> &n);
void move_to_back(Element<T> &n);
friend ostream& operator<<(ostream& out, PAL<T>& sl){
sl.print_list(out);
return out;
};
};
template<typename T>
pair<Element<T>*, Element<T>*> PAL<T>::find(string name){
pair<Element<T>*, Element<T>*> *result (nullptr);
Element<T>* x = nullptr;
Element<T>* y = nullptr;
for (Element<T> *n = back_; n != nullptr; n = n -> next_){
if (n -> name_ == name){
x = n;
cout << x;
break;
}
y = n;
}
result -> first = x;
result -> second = y;
return *result;
}
pair<Element<T>*, Element<T>*> *result (nullptr);
followed by
result -> first = x;
result -> second = y;
return *result;
is a problem.
You haven't allocated memory for result and proceeded to use it as though it points to a valid object.
Simplify it. Remove result altogether and change the return statement to:
return {x, y};
Added override for operator<< for my class but i am getting inside a function:
error: no match for ‘operator<<’ (operand types are
‘std::basic_ostream’ and ‘Edge’)
cout << "Adding: " << edge;
But if i try to use this code everything works as expected:
Edge edge1("A", "B", 3);
Edge* edge2 = new Edge("A", "B", 3);
cout << edge1 << endl;
cout << *edge2 << endl;
Here is code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Node {
public:
string name;
Node() {}
Node(string name):name(name) {}
bool operator==(const Node& other) {
return name == other.name;
}
};
class Edge {
public:
Node x;
Node y;
int cost;
Edge(string x_name, string y_name, int cost) {
this->x = Node(x_name);
this->y = Node(y_name);
this->cost = cost;
}
Edge(Node x, Node y, int cost):x(x),y(y) {}
bool operator==(const Edge& other) {
return x == other.x && x == other.y && cost == other.cost;
}
};
class Graph {
public:
vector<Edge> edges;
vector<Node> nodes;
bool has_node(Node node) {
return find(nodes.begin(), nodes.end(), node) != nodes.end();
}
bool has_edge(Edge edge) {
return find(edges.begin(), edges.end(), edge) != edges.end();
}
void add(string x_name, string y_name, int cost) {
Node x(x_name);
Node y(y_name);
bool has_not_x = !has_node(x);
bool has_not_y = !has_node(y);
if (has_not_x) {
nodes.push_back(x);
}
if (has_not_y) {
nodes.push_back(y);
}
if (has_not_x || has_not_y) {
add(x, y, cost);
}
}
void add(Node x, Node y, int cost) {
Edge edge(x, y, cost);
if (!has_edge(edge)) {
cout << "Adding: " << edge;
edges.push_back(edge);
}
}
};
ostream& operator<<(ostream& os, const Node& node)
{
os << "(" << node.name << ")";
return os;
}
ostream& operator<<(ostream& os, const Edge& edge)
{
os << edge.x << "-" << edge.cost << "-" << edge.y;
return os;
}
int main()
{
Graph* graph = new Graph();
graph->add("A", "C", 1);
return 0;
}
Because the compiler reads the code linearly, it is not aware that the overload of operator<<(ostream&, const Edge&) exists yet.
If you place a declaration of the overload before the definition of the class, the code will compile:
// Place the function declaration before the class
// to inform the compiler of the overload's existence.
ostream& operator<<(ostream& os, const Edge& edge);
class Graph {
public:
vector<Edge> edges;
vector<Node> nodes;
// and so on...
There are many questions like this but after looking at some cases, I guess this question is case-specific so I post my code and pointed out where the problem takes place may you be patient reading my code?
uniBTree.h
#ifndef uniBTree_H
#define uniBTree_H
#include "uniTreeNode.h"
#include <cassert>
template<class T>
class uniBTree {
private:
uniTreeNode<T> *root;
int delete_helper(uniTreeNode<T> *);
uniTreeNode<T> *insert_helper(uniTreeNode<T> *, const T);
void in_print_helper(const uniTreeNode<T> *) const;
void pre_print_helper(const uniTreeNode<T> *) const;
void post_print_helper(const uniTreeNode<T> *) const;
public:
uniBTree(void);
uniBTree(uniTreeNode<T> *r);
~uniBTree(void);
void insert(const T i);
void in_print(void) const;
void pre_print(void) const;
void post_print(void) const;
};
template<class T>
uniBTree<T>::uniBTree(void)
{
root = NULL;
}
template<class T>
uniBTree<T>::uniBTree(uniTreeNode<T> *r)
{
root = r;
}
template<class T>
int uniBTree<T>::delete_helper(uniTreeNode<T> *n)
{
int count = 0;
if (n == NULL)
return 0;
count += delete_helper(n->get_left());
count += delete_helper(n->get_right());
delete n;
count++;
return count;
}
template<class T>
uniBTree<T>::~uniBTree(void)
{
int count = delete_helper(root);
std::cout << "uniBTree<T>::~uniBTree<T>(void)\n";
std::cout << count << " nodes deleted\n";
}
template<class T>
void uniBTree<T>::in_print() const
{
in_print_helper(root);
}
template<class T>
void uniBTree<T>::pre_print() const
{
pre_print_helper(root);
}
template<class T>
void uniBTree<T>::post_print() const
{
post_print_helper(root);
}
template<class T>
void uniBTree<T>::in_print_helper(const uniTreeNode<T> *current) const
{
if (current == NULL)
return;
in_print_helper(current->get_left());
current->print();
in_print_helper(current->get_right());
}
template<class T>
void uniBTree<T>::pre_print_helper(const uniTreeNode<T> *current) const
{
if (current == NULL)
return;
current->print();
pre_print_helper(current->get_left());
pre_print_helper(current->get_right());
}
template<class T>
void uniBTree<T>::post_print_helper(const uniTreeNode<T> *current) const
{
if (current == NULL)
return;
post_print_helper(current->get_left());
post_print_helper(current->get_right());
current->print();
}
template<class T>
void uniBTree<T>::insert(const T i)
{
if (root == NULL)
root = new uniTreeNode<T>(i, NULL, NULL);
else
insert_helper(root, i);
}
template<class T>
uniTreeNode<T> *uniBTree<T>::insert_helper(uniTreeNode<T> *current, const T i)
{
if (current == NULL) {//this is will only dealed by attempting to visit leaves...
//if root is null, it'll be handled in insert
uniTreeNode<T> *child = new uniTreeNode<T>(i, NULL, NULL);
assert(child != NULL);
return(child);
}
if (i < current->get_data())
current->set_left(insert_helper(current->get_left(), i));
else
current->set_right(insert_helper(current->get_right(), i));
return(current);
}
#endif
uniTreeNode.h
#ifndef uniTreeNode_H//for redefinition
#define uniTreeNode_H
#include <iostream>
//using namespace std; don't use using namespace xxx and include source file in .h file
template<typename T>
class uniTreeNode {
private:
T data;
uniTreeNode<T> *left;
uniTreeNode<T> *right;
public:
//uniTreeNode<T>(void);
uniTreeNode(T d, uniTreeNode<T> *l, uniTreeNode<T> *r);
T get_data(void) const;
uniTreeNode<T> *get_left(void) const;
uniTreeNode<T> *get_right(void) const;
void set_left(uniTreeNode<T> *l);
void set_right(uniTreeNode<T> *r);
void print() const;
};
template<typename T>
uniTreeNode<T>::uniTreeNode/*remember syntax here*/
(T d , uniTreeNode<T> *l = NULL, uniTreeNode<T> *r = NULL)
{
data = d;
left = l;
right = r;
}
template<typename T>
T uniTreeNode<T>::get_data(void) const
{
return data;
}
template<typename T>
uniTreeNode<T> * uniTreeNode<T>::get_left(void) const
{
return left;
}
template<typename T>
uniTreeNode<T> * uniTreeNode<T>::get_right(void) const
{
return right;
}
template<typename T>
void uniTreeNode<T>::set_left(uniTreeNode<T> *l)
{
left = l;
}
template<typename T>
void uniTreeNode<T>::set_right(uniTreeNode<T> *r)
{
right = r;
}
template<typename T>
void uniTreeNode<T>::print() const
{
std::cout << "data is " << data << std::endl;
}
#endif
date.h
#include <ostream>
class date{
private:
int y;
int m;
int d;
public:
date();//default constructor
date(const long int);//used by cplr as convert constructor
date(int, int , int);
friend bool operator<(const date &d1, const date &d2);//d1 is for left-hand date
friend bool operator>(const date &d1, const date &d2);
bool operator==(date d);
bool operator!=(date d);
date &operator=(date d);
friend std::ostream &operator<<(std::ostream &out, date d);
friend std::istream &operator>>(std::istream &in, date d);
};
date.cc
#include <iostream>
#include <cstdio>
#include <time.h>
#include <cstring>
#include "date.h"
date::date(){
y = m = d = 0;
}
date::date(int Y, int M, int D){
y = Y;
m = M;
d = D;
}
date::date(const long int s){//#second since 1970/1/1 00:00:00
struct tm *buf;
buf = gmtime(&s);
y = (buf->tm_year+1900);
m = buf->tm_mon+1;
d = buf->tm_mday;
}
bool operator<(const date &d1, const date &d2){
bool result;//sizeof(bool) is 1
if(d1.y < d2.y) result = true;
else if(d1.y == d2.y){
if(d1.m < d2.m) result = true;
else if(d1.m == d2.m){
if(d1.d < d2.d) result = true;
else result = false;
}
else result = false;
}
else result = false;
return result;
}
bool operator>(const date &d1, const date &d2){
bool result;//sizeof(bool) is 1
if(d1.y > d2.y) result = true;
else if(d1.y == d2.y){
if(d1.m > d2.m) result = true;
else if(d1.m == d2.m){
if(d1.d > d2.d) result = true;
else result = false;
}
else result = false;
}
else result = false;
return result;
}
bool date::operator==(date d){
return (this->y==d.y && this->m==d.m && this->d==d.d);
}
bool date::operator!=(date d){
return (this->y!=d.y || this->m!=d.m || this->d!=d.d);
}
date &date::operator=(date d){
this->y = d.y;
this->m = d.m;
this->d = d.d;
return *this;
}
std::ostream &operator<<(std::ostream &out, date d){
out << d.y << "/" << d.m << "/" << d.d << std::endl;
return out;
}
std::istream &operator>>(std::istream &in, date d){
in >> d.y >> d.m >> d.d ;
return in;
}
main function
#include "uniBTree.h"
#include "date.h"
#include <cstdio>
int main(){
date d1 = 100000000;//convert constructor
uniTreeNode<date> node(d1, NULL, NULL);
printf("%p %p\n", node.get_left(), node.get_right());
std::cout << node.get_data() << std::endl;
date d2 = 86401;
date d3 = 200000000;
uniBTree<date> btree(&node);
return 0;
}
I tested and found that its &node that is invalid. I think it is because it tries to "release" btree at the end of the program and when the root is encountered, because it points to node, it can't perform good thing.
I have two question:
if construct a node like what I did,(uniTreeNode<date> node(xxx, xxx, xxx);) was the object "NEW"ed by the program?
for the uniTreeNode<T> class template, I didn't write its destructor!! So, like what I say above, when node,which is pointed by root of btree, is to be released is there so-called "default destructor"? and is it called here ? And most importantly, is "DELETE" used by the program?
If one of the two question above is no, is it why the problem arise?
EDIT: now the problem is shown, but how can I adjust my code to fix this? any one any idea?
EDIT: just modify like this:
uniTreeNode<date> *nodeptr = new uniTreeNode<date>(d1, NULL, NULL);
p.s. if not indirectly using a pointer to refer to our root of the btree(thus using new), new isn't used, and delete shouldn't be used; by this choice, delete_helper of uniTreenode should use this:
if(n != root){
delete n;
count++;
}
but this does not solve the problem...
the ultimate question is:
"can we release object without using delete(because it isn't obtained from newing) in c++?"
REPLY:
My "release"/"allocated" is actually saying about the memory, without specifying HOW it is done...but it's a big issue anyway
You say "you can do that but it is almost always the wrong answer";you mean that I should use DELETE but not directly call the destructor?(actually that doesn't seem proper at all)
-->please justify here
Btw, for those instance NEWed by me, is it necessary for them to be DELETED by a statement if I want to release them? or they'll also be dealt like those automatic variable instance?(back when out of scope, by compiler)
-->please correct the above if needed
another Q: isn't there ANY existing statement I can use to do things, like what DELETE does, for those automatic instance? or, I can only call destructor, if I wish?
Answer to your questions:
No, it allocated memory on the stack at compilation time and just ran the constructor on that.
You can't delete a pointer not allocated using new. The compiler inserts a call to the destructor (default or not) for uniTreeNode when the object node is done in main().
So to surmise, you cannot use delete on a pointer that is not allocated using new.
Simplest fix would be to allocate node using new:
uniTreeNode<date>* node = new uniTreeNode<date>(d1);
uniBTree<date> btree(node);
Learn to use valgrind.
It tells you right away what the problem is, you're deleting a stack object in the uniBTree destructor
==23648== Invalid free() / delete / delete[] / realloc()
==23648== at 0x4A0736C: operator delete(void*) (vg_replace_malloc.c:480)
==23648== by 0x400D78: uniBTree<date>::delete_helper(uniTreeNode<date>*) (uniBTree.h:48)
==23648== by 0x400CD5: uniBTree<date>::~uniBTree() (uniBTree.h:56)
==23648== by 0x400B91: main (main.cc:17)
==23648== Address 0x7fefffab0 is on thread 1's stack
==23648==
The destructor calls delete but &node was not created by new (you can tell that because you didn't write new!)
###MyClass.h###
#ifndef _MyClass
#define _MyClass
#include <string>
using namespace std;
class MyClass
{
public:
MyClass(const string name, const string text);
void display(ostream & out) const;
MyClass & operator = (const MyClass & m);
int compare(const MyClass & right) const;
private:
string _name;
string _text;
};
bool operator < (const MyClass & left, const MyClass & right);
ostream & operator << (ostream & out, const MyClass & mc);
#endif
###Node.h###
#include <string>
#include "MyClass.h"
using namespace std;
typedef MyClass * DataType;
class Node
{
private:
DataType item; // data
Node * lchild; // left child pointer
Node * rchild; // right child pointer
public:
Node(DataType Item);
DataType getItem() const;
void setItem(const DataType & data);
Node* getLChild() const;
void setLChild(Node * p);
Node* getRChild() const;
void setRChild(Node * p);
virtual ~Node();
};
###BST.h###
#include "Node.h"
using namespace std;
class BST
{
private:
Node * root;
bool Search(const DataType item, Node * r) const;
void Insert (DataType item, Node * ptr);
void Destructor(const Node * r);
public:
BST();
bool IsEmpty() const;
void Insert(const DataType item);
bool Search(const DataType item) const;
virtual ~BST();
};
###MyClass.cpp###
#include <iostream>
#include "MyClass.h"
using namespace std;
MyClass::MyClass(const string name, const string text)
{
_name = name;
_text = text;
}
void MyClass::display(ostream & out) const
{
out << "Name: " << _name << endl;
out << "Text: " << _text << endl;
}
MyClass & MyClass::operator = (const MyClass & m)
{
if (this == & m)
return *this;
_name = m._name;
_text = m._text;
return *this;
}
int MyClass::compare(const MyClass & right) const
{
return _name.compare(right._name);
}
bool operator < (const MyClass & left, const MyClass & right)
{
return left.compare(right) > 0;
}
ostream & operator << (ostream & out, const MyClass & mc)
{
mc.display(out);
return out;
}
###Node.cpp###
#include "Node.h"
Node::Node(DataType Item):item(Item)
{
lchild = 0;
rchild = 0;
}
DataType Node::getItem() const
{
DataType anItem = item;
return anItem;
}
void Node::setItem( const DataType & data)
{
item = data;
}
Node* Node::getLChild() const
{
Node * p = lchild;
return p;
}
void Node::setLChild(Node * p)
{
lchild = p;
}
Node* Node::getRChild() const
{
Node * p = rchild;
return p;
}
void Node::setRChild(Node * p)
{
rchild = p;
}
Node::~Node()
{
}
###BST.cpp###
#include <iostream>
#include "BST.h"
using namespace std;
bool BST::Search(const DataType item) const
{
return Search(item, root);
}
bool BST::Search(const DataType item, Node * r) const
{
if(r != 0)
{
if (item == r->getItem())
return true;
else
{
if (item < r->getItem())
return Search(item, r->getLChild());
else
return Search(item, r->getRChild());
}
}
else
return false;
}
BST::BST()
{
root = 0;
}
bool BST::IsEmpty() const
{
return (root == 0);
}
void BST::Insert(const DataType item)
{
if(root == 0)
root = new Node(item);
else
Insert(item, root);
}
void BST::Insert(DataType item, Node * ptr)
{
if (item < ptr->getItem())
{
if (ptr->getLChild() == 0)
ptr->setLChild(new Node(item));
else
Insert(item, ptr->getLChild());
}
else
{
if (ptr->getRChild() == 0)
ptr->setRChild(new Node(item));
else
Insert(item, ptr->getRChild());
}
}
void BST::Destructor(const Node * r)
{
if(r!=0)
{
Destructor( r->getLChild());
Destructor( r->getRChild());
delete r;
}
}
BST::~BST()
{
Destructor(root);
}
###main.cpp###
#include <iostream>
#include "MyClass.h"
#include "BST.h"
using namespace std;
void main()
{
MyClass * mc1 = new MyClass("Tree","This is a tree");
MyClass * mc2 = new MyClass("Book","This is a book");
MyClass * mc3 = new MyClass("Zoo","This is a zoo");
BST * tree = new BST();
tree->Insert(mc1);
tree->Insert(mc2);
tree->Insert(mc3);
cout << boolalpha << ("Book" < "Tree") << endl;
cout << (mc2 < mc1) << endl;
cout << (tree->Search(new MyClass("Book",""))) << endl;
}
Result is true false false
I don't know what's wrong with my operator overloading? (mc2 should
less than mc1)
I'm not sure if this is correct for searching a "MyClass" node in a BST?
and the result is "not found"....I traced it into "BST.cpp",
and found that the problem also occurs at " if (item < r->getItem()) "
Can anyone help me or give me a hint....thank you so much!
Here you are just comparing pointers, i.e memory addresses:
cout << (mc2 < mc1) << endl;
To compare the objects, you need to dereference the pointers:
cout << ((*mc2) < (*mc1)) << endl;
In your code snippet, there is no reason for mc1, mc2, etc. to be pointers, so you could avoid the problem by creating objects on the stack directly:
MyClass mc1("Tree","This is a tree");
and so on. I would even go further and say that you should only dynamically allocate objects with new if you really are sure you need to and have good reasons not to allocate automatically on the stack. And if you really must use dynamically allocated pointers, have a look at C++ smart pointers.