I've been trying to make a template class (called List) which stores different type of objects. I created Base class to be like base in my program and Human class. Base can create new Human and to have access to them all, has a (private) pointer to List * first_h (in every List is stored Human* me, List * next and List * first_h (first_h in list)).
The problem is, when I add like more than 1 Human to my Base, I can't display them properly. I think it's because of creating new Human's in Base method (void Base::create_human(string name)) but everything I did don't work it out.
There are my classes:
class Human
{
private:
string name;
public:
Human(string name) { this->name = name; }
void display() { cout << "My name: " << name << endl; }
};
template <class T>
class List
{
private:
T* me;
List <T>* next;
List <T>* first;
public:
void set_me(T* me) { this->me = me; }
T* get_me() { return this->me; }
void set_next(List* next) { this->next = next; }
List <T>* get_next() { return this->next; }
void set_first(List* first) { this->first = first; }
List <T>* get_first() { return this->first; }
void add(T*& created);
void display();
};
class Base
{
private:
List <Human>* first_h;
public:
void set_first_h(List <Human>*& first) { this->first_h = first; }
List <Human>* get_first_h() { return this->first_h; }
void create_human(string name)
{
Human* created = new Human(name);
this->first_h->add(created);
}
};
and methods:
template <class T>
void List<T>::add(T*& created)
{
List <T>* temp = this->get_first();
List <T>* new_list;
if ((this->get_me()) == nullptr)
{
this->set_next(nullptr);
this->set_me(created);
this->set_first(this);
}
else
{
new_list = new List <T>;
temp = this->get_first();
while (temp != nullptr)
{
temp = temp->get_next();
}
new_list->set_next(nullptr);
new_list->set_first(this->get_first());
temp->set_next(new_list);
}
}
template <class T>
void List<T>::display()
{
List <T>* temp_list = this;
T* temp;
if (temp_list == nullptr)
{
std::cout << "There is nothing!" << endl;
}
while (temp_list != nullptr)
{
temp = temp_list->get_me();
temp->display();
temp_list = temp_list->get_next();
}
std::cout << "End!" << endl;
}
and my main function:
int main()
{
Base Main;
List <Human>* first_h = new List <Human>();
Main.set_first_h(first_h);
Main.create_human("Jane");
Main.create_human("John");
Main.create_human("Mary");
Main.get_first_h()->display();
system("pause");
return 0;
}
Sorry for my English and thank you in advance!
Edit:
I found out what was wrong:
in add function:
new_list->set_next(nullptr);
new_list->set_me(created);
new_list->set_first(this->get_first());
temp->set_next(new_list);
I forgot about:
new_list->set_me(created);
the mistake in add function as one of you wrote.
Your loop
while (temp != nullptr)
{
temp = temp->get_next();
}
runs till temp is nullptr and then you do
temp->set_next(new_list);
So, as you see, inside set_next() the this pointer is nullptr.
Please learn how to use a debugger and look at the call stack.
Related
i am simply creating a payroll system that has a employee name and a working hours for that employee.. the data is supposed to be stored in a linked list data structure, but i can not connect the linked list to the object of the class employee, i tried making the pay roll linked list (i.e empList) as a static member so that all the objects of the class can use the same list object and data can be stored but once i compile my code i get an error of "undefined reference to employee::empList" at line 130 that is the last line of constructor, same error on line 150 that is a print pay roll function.. where ever i am trying to call any payRollLinkedList class's function in employee class it gives error.. bottom line is that all i want is to data be stored in a doubly linked list of employees and i can not access the list.
#include <iostream>
using namespace std;
class payRollLinkedList;
class node
{
private:
node* previousPointer;
string name;
int hoursWorked;
node* nextPointer;
friend class payRollLinkedList;
public:
explicit node(const string argName, const int argHoursWorked)
: previousPointer{nullptr}, name{argName}, hoursWorked{argHoursWorked}, nextPointer{nullptr}
{}
};
class payRollLinkedList
{
private:
node* headPointer{nullptr};
node* tailPointer{nullptr};
node* getNewNode(const string argName, const int argHoursWorked)
{
return new node(argName, argHoursWorked);
}
public:
void addAtBack(const string argName, const int argHoursWorked)
{
node* newNode{getNewNode(argName, argHoursWorked)};
if(isEmpty())
{
headPointer = tailPointer = *newNode;
}
else
{
tailPointer->nextPointer = newNode;
newNode->previousPointer = tailPointer;
tailPointer = newNode;
newNode = nullptr;
delete newNode;
}
}
bool deleteNode(string argName)
{
node* currentPointer{headPointer};
if(isEmpty())
{
cout <<"the list is already empty\n";
return false;
}
else
{
while(currentPointer != nullptr)
{
if(currentPointer->name == argName)
{
if(currentPointer == headPointer)
{
node* tempPointer{headPointer};
headPointer = headPointer->nextPointer;
tempPointer->nextPointer = nullptr;
headPointer->previousPointer = nullptr;
delete tempPointer;
break;
}
if(currentPointer == tailPointer)
{
node*tempPointer{tailPointer};
tailPointer = tailPointer->previousPointer;
tempPointer->previousPointer = nullptr;
tailPointer->nextPointer = nullptr;
delete tempPointer;
break;
}
node* tempPointer{currentPointer};
node* nextPtr{tempPointer->nextPointer};
currentPointer = currentPointer->previousPointer;
currentPointer->nextPointer = nextPtr;
nextPtr->previousPointer = currentPointer;
tempPointer->nextPointer = nullptr;
tempPointer->previousPointer = nullptr;
currentPointer = nullptr;
nextPtr = nullptr;
delete tempPointer;
delete currentPointer;
delete nextPtr;
}
else
currentPointer = currentPointer->nextPointer;
}
return true;
}
}
void print()
{
if(isEmpty())
{
cout <<"nothing to show\n";
return;
}
else
{
node* currentPointer{headPointer};
while(currentPointer != nullptr)
{
cout <<currentPointer->name <<"\t";
currentPointer = currentPointer->nextPointer;
}
}
}
bool isEmpty()
{
return headPointer == nullptr? true : false;
}
};
class employee
{
private:
string name;
int hoursWorked;
static payRollLinkedList empList;
public:
employee()
: name{""}, hoursWorked{0}
{}
employee(string argName, int argHoursWorked)
{
name = argName;
hoursWorked = argHoursWorked;
empList.addAtBack(name, hoursWorked);
}
void printPayRoll()
{
empList.print();
}
};
int main()
{
employee emp("usman", 12);
employee emp1("ali", 12);
emp.printPayRoll();
}
https://en.cppreference.com/w/cpp/language/static
You need to define static member of class at global scope (out of class).
i suggest you to split your code .h and .cpp files and define the member in .cpp file.
payRollLinkedList employee::empList;
I'm trying to implement a templated singly linked list and I'm fairly new to C++
#include <iostream>
#include <string>
#define NEWL "\n"
#define PRINT(s) std::cout << s
#define PRINTL(s) std::cout << s << NEWL
#define PRINTERR(e) std::cerr << e << NEWL
////// Class for a Node
template<class Data> class Node {
Node<Data>* next_ptr;
Data data;
public:
Node(Node<Data>* nxt_ptr) :next_ptr(nxt_ptr) {};
Node(Data d, Node<Data>* nxt_ptr) :data(d), next_ptr(nxt_ptr) {};
Node<Data>* get_next() { return next_ptr; }
Data& get_data() { return data; }
friend std::ostream& operator<<(std::ostream& out, const Node<Data>& node) {
out << node.data;
return out;
};
};
////// Class for a SinglyLinkedList
template<class Data> class SLinkedList {
Node<Data>* head_ptr;
int max_size;
public:
SLinkedList() : head_ptr(nullptr) {};
bool is_empty() {
return head_ptr == nullptr;
};
bool is_full() {
return get_size() == max_size;
};
int get_size() {
if (is_empty()) {
return 0;
}
int count = 0;
for (Node<Data>* it_ptr = head_ptr; it_ptr != nullptr; it_ptr = it_ptr->get_next()) {
count++;
}
return count;
};
void add(Data d) {
if (is_full()) {
throw std::exception("List is full!");
}
Node<Data> new_node(d, head_ptr);
head_ptr = &new_node;
};
void print_content() {
int count = 1;
PRINTL("This list contains:");
for (Node<Data>* it_ptr = head_ptr; it_ptr != nullptr; it_ptr = it_ptr->get_next()) {
PRINTL("\t["<< count << "]" << " at " << it_ptr << " : " << *it_ptr);
count++;
}
}
};
////// Main function
int main()
{
SLinkedList<int> sll;
sll.add(42);
sll.print_content();
}
I can't get this to work. Somehow iterating the list with for-loops does not work. It always results in an Reading Access Violation Exception about a pointer to 0xCCCCCCD0 and I have no idea how to fix this.
Your add function is incorrect
Node<Data> new_node(d, head_ptr);
creates a new function local Node in add. You then set head to the address of that local variable. When the function ends all local variables are destroyed so now head points to an object that no longer exists.
To fix that you need to use the new keyword to create a dynamic object that will live on after the function ends.
Node<Data>* new_node = new Node(d, head_ptr);
head_ptr = new_node;
The down side with this is you need to remember to call delete on all of the nodes you created in the list destructor.
You also have some other bugs in your code. You never set max_size in your constructor so using it at all except to give it a value is undefined behavior as we have no idea what the value of it is going to be. You also never increase the size of the list when you add nodes into the list.
I am having a class Car, now I want to make linked list of Car objects. So for this I am having a Node class to hold data for each node.
class StringOfCar;
class Node
{
private:
Node* next;
Car* data;
Node ()
{
next = 0;
data = 0;
}
public:
friend class StringOfCar;
};
And StringOfCar
class StringOfCar
{
private:
Node* head;
Node* tail;
public:
StringOfCar(){
head=0;
tail=0;
}
void output();
void push (Car &);
};
Now I push the elements without any problem with this function :
void StringOfCar::push(Car & new_car)
{
Car *currentCarPtr;
Node *currentNodePtr;
currentNodePtr = new Node;
currentCarPtr = new Car(new_car);
currentNodePtr->next = 0;
currentNodePtr->data = &new_car;
if (head == 0)
{
head = currentNodePtr;
tail = currentNodePtr;
}
else
{
tail->next = currentNodePtr;
tail = currentNodePtr;
}
}
But when I try to output, program stops abruptly.I have output() for Car class also. Output function for both class is as follow :
void StringOfCar::output(){
Node * currentNodePtr = head;
if (head == 0)
cout << "NO cars \n";
else
{
while (currentNodePtr != 0)
{
currentNodePtr->data->output();
currentNodePtr = (currentNodePtr->next);
}
}
}
And for Car class :
void Car::output()
{
cout<<"\nreportingMark "<<setw(3)<<reportingMark;
cout<<"\ncarNumber "<< setw(8)<< carNumber;
cout<<"\nkind " << setw(13)<<KIND_ARRAY[kind];
if (loaded==true)
{
cout<<" \nloaded true";
}
else if (loaded == false)
{
cout<< "\nloaded false";
}
cout<< "\ndestination "<<setw(7)<<destination<<endl;
}
When I comment currentNodePtr->data->output(); this line, it works fine. What can be problem ? Please help
I think the problem is in this line:
currentNodePtr->data = &new_car;
of the function void StringOfCar::push(Car & new_car).
That should be
currentNodePtr->data = currentCarPtr;
I'm creating a game of snake in C++, but I'm having some trouble utilizing my linkedList class that I've created. When I made snake in Python, I made lists within a list to represent the x and y position of each circle that makes up my snake. I am trying to do something similar in C++. Here is my templatized linkedList class I made if for some reason you need to see it:
#ifndef LLIST_H_INCLUDED
#define LLIST_H_INCLUDED
#include <cstddef>
#include <iostream>
using namespace std;
template <class T>
class linkedList
{
public:
class node
{
public:
///node class attributes
T mPayload;
node* mNext;
///constructor
node(T toucan):mPayload(toucan),mNext(NULL)
{}
///destructor
~node()
{
///cascading delete
if(mNext)
delete mNext;
}
///node class methods
};
///linkedList class attributes
node* mStart;
///constructor
linkedList():mStart(NULL)
{}
///destructor
~linkedList()
{
///initializes the cascading delete.
if(mStart)
delete mStart;
}
///linkedList class methods
T mReturnT(int indx)
{
if(!mStart)
return NULL;
else
{
node* cur;
for(int i = 0; i<indx; i++)
{
if(!cur->mNext)
{
cout << "Indx out of range. Deleting last item." << endl;
break;
}
cur = cur->mNext;
}
delete cur;
return cur->mPayload;
}
}
void mInsert(int indx, T data)
{
///Insert an item at a given position.
///The first argument is the index of
///the element before which to insert.
node* cur = mStart;
for(int i = 0; i < indx; i++)
{
if(!cur->mNext)
break;
else
{
cur = cur->mNext;
}
}
node* N = new node(data);
node* temp = cur->mNext;
cur->mNext = N;
N->mNext = temp;
}
T mPop()
{
///Removes the last item in the list,
///and returns it.
if(!mStart)
return NULL;
else
{
node* cur = mStart;
while(cur->mNext)
{
cur = cur->mNext;
}
T var = cur->mPayload;
delete cur;
return var;
}
}
int mSize()
{
if(!mStart)
return 0;
else
{
node* cur = mStart;
int counter = 1;
while(cur->mNext)
{
cur = cur->mNext;
counter++;
}
delete cur;
return counter;
}
}
void mPrint()
{
///prints all values in a list.
node* cur;
if(!mStart)
cout << "List is empty." << endl;
else
{
cur = mStart;
cout << "[";
while(cur)
{
cout << cur->mPayload << " ";
cur = cur->mNext;
}
cout << "]" << endl;
delete cur;
}
}
void swapNodes(node* N)
{
///idk
}
void bubbleSort()
{
if(!mStart)
return;
node* cur = mStart;
while(cur)
{
cout << cur->mPayload << endl;
if(cur->mRight->mFrequency > cur->mFrequency)
{
swapNodes(cur);
cur = mStart;
}
else
cur = cur->mRight;
}
delete cur;
}
};
#endif // LLIST_H_INCLUDED
Now in my main.cpp, I would like to do something like this so that I have a linked list of linked lists:
linkedList<linkedList> p1Snake;
linkedList<int> startingPiece;
startingPiece.mInsert(0,600); //This is the starting y position of
// p1snake added to the front of the list.
startingPiece.mInsert(0,350); //This is the starting x position of
//p1snake added to the front of the list.
p1Snake.mInsert(0,startingPiece);
My problem arises on the first line of that code. Error: type/value mismatch at argument 1 in template parameter list for 'template class class linkedList. How can I solve this?
Your lnkedList class has 1 templatized type T, so the syntax of variable definition should be:
linkedList<type> variableName;
by recursion, type can be linkedList, but it should still be in above form (there is type).
So for example if the last data type is int:
linkedList<linkedList<int> > variableName;
This needs to be a linked list of a linked list of something:
linkedList<linkedList> p1Snake;
Something along these lines:
linkedList< linkedList< something > > p1Snake;
You may want to refer to this article titled "Linked List Template and Binary Search Tree": http://www.cplusplus.com/forum/articles/40773/
Hi
I have some issue regarding constructor and destructor. I have list class, which has two inner classes, one private class for the list nodes, and one public iterator class.
Now for the issue, I have written a non-member print function which uses the inner iterator class. When i use this non-member function it will end calling the destructor for the iterator. It doesn't end here though because for some reason it will also call for the list class's destructor. Which causes some problem when I want to print the list content again.
I don't understand why it call the list class destructor as well and wonder if someone kindly can tell me that, and how I should fix it.
I have attached all the code related to the problem
Main
#include <iostream>
#include "sorted_list.h"
#include "iterator.h"
using namespace std;
void list_print(ostream& os, sorted_list list)
{
sorted_list::iteratorn it(&list);
while( ! it.iterator_end())
{
os << "key = " << setw(3) << it.iterator_get_key() << ", "
<< "value = " << setw(5) << it.iterator_get_value() << endl;
it.iterator_next();
}
os << endl;
}
int main()
{
sorted_list a;
a.insert(4,4);
a.insert(5,5);
list_print(cout,a);
list_print(cout,a);
}
sorted_list.cc
#include "sorted_list.h"
sorted_list::sorted_list()
{
cout << "construct sorted_list" << endl;
this->first = 0;
}
sorted_list::~sorted_list()
{
cout << "destruct sorted_list" << endl;
destroy(this->first);
}
void sorted_list::destroy(list_link* item)
{
cout << "destroy list_link" << endl;
if(item)
{
destroy(item->next);
delete item;
}
}
void sorted_list::insert(int key, double value)
{
list_link *curr;
list_link *prev = 0;
curr = first;
while(curr)
{
if(value < curr->value)
break;
prev = curr;
curr = curr->next;
}
if(this->first == 0 || prev == 0) //if empty or add first
{
//first = create(key, value, this->first);
first = new list_link(key, value, this->first);
}
else if(curr == 0)
{
//prev->next = create(key, value, 0);
prev->next = new list_link(key, value, 0);
}
else
{
//prev->next = create(key, value, curr);
prev->next = new list_link(key, value, curr);
}
}
void sorted_list::remove(my_key_type key)
{
list_link *curr = first;;
list_link *prev = 0;
while(curr)
{
if(curr->key == key)
{
list_link *remove;
if(prev == 0)
{
first = curr->next;
delete curr;
curr = first;
}
else
{
remove = curr;
curr = curr->next;
prev->next = curr;
delete remove;
}
continue;
}
prev = curr;
curr = curr->next;
}
}
sorted_list::list_link* sorted_list::clone(list_link* item)
{
list_link* copyItem= new list_link(item->key,item->value,0);
if(item->next!= 0)
copyItem->next=clone(item->next);
return copyItem;
// ADD YOUR CODE HERE ( 4 well formatted lines in reference solution )
}
void sorted_list::copy(sorted_list* my_this_destination)
{
if (my_this_destination->first == 0) // copy if empty
{
cout << "Copy" << endl;
//list_destroy(my_this_destination);
my_this_destination->first = clone(first);
}
}
double sorted_list::find(int key)
{
list_link *travel = this->first;
while(travel)
{
cout << travel->key << "==" << key << endl;
if(travel->key == key)
return travel->key;
travel = travel->next;
}
return -1;
}
int sorted_list::size()
{
list_link *travel = this->first;
int i = 0;
while( travel )
{
travel = travel->next;
i++;
}
return i;
}
sorted_list.h
#ifndef _SORTED_LIST_H_
#define _SORTED_LIST_H_
#include <iostream>
#include <iomanip>
using namespace std;
typedef int my_key_type;
typedef double my_value_type;
class sorted_list
{
public:
sorted_list();
~sorted_list();
void insert(int key, double value);
void remove(my_key_type key);
void copy(sorted_list* my_this_destination);
void destroy();
void init(struct my_list* my_this);
void print();
void print2();
double find(int key);
int size();
private:
class list_link // An inner class inside sorted_list
{
public:
list_link (my_key_type key, my_value_type value, list_link* next = 0);
~list_link();
my_key_type key;
my_value_type value;
list_link *next;
};
list_link* first;
list_link* clone(list_link* item);
void destroy(list_link* item);
// More declarations
public:
class iteratorn
{
public:
iteratorn();
~iteratorn();
iteratorn(sorted_list *item);
list_link* list_begin();
bool iterator_end();
void iterator_next();
int iterator_get_key();
double iterator_get_value();
private:
sorted_list::list_link* current;
};
};
#endif
iteratorn.cc
#include "iterator.h"
#include "sorted_list.h"
sorted_list::iteratorn::iteratorn()
{
}
sorted_list::iteratorn::iteratorn(sorted_list *list)
{
cout << "construct iteratorn" << endl;
this->current = list->first;
}
sorted_list::iteratorn::~iteratorn()
{
cout << "destruct iteratorn" << endl;
}
sorted_list::list_link* sorted_list::iteratorn::list_begin()
{
return current;
}
void sorted_list::iteratorn::iterator_next()
{
current = current->next;
}
int sorted_list::iteratorn::iterator_get_key()
{
return current->key;
}
double sorted_list::iteratorn::iterator_get_value()
{
return current->value;
}
list_link.cc
#include "sorted_list.h"
sorted_list::list_link::list_link(my_key_type key, my_value_type value, list_link* next)
{
this->key = key;
this->value = value;
this->next = next;
}
sorted_list::list_link::~list_link()
{
cout << "list_link destructor" << endl;
}
Your function void list_print(ostream& os, sorted_list list) takes a sorted_list parameter by copy. A quick and dirty fix (that you should do anyways for performance reasons) is the following:
void list_print(ostream& os, const sorted_list& list)
Now, your iteratornclass takes a mutable list, so this won't work as you expect. You will have quite a few methods to change to make this work.
In any case, your real problem is the lack of a proper copy-constructor. Right now, when you "copy" a list, both end up sharing the same elements, but your destructor is written as if each list owns it's own nodes. Define a proper copy operation and it will solve your problem.
More elaborate help on how to solve the problem: (untested)
Change signature:
void list_print(ostream& os, const sorted_list& list);
Declare + define copy constructor:
sorted_list::sorted_list (const sorted_list& other);
Change iteratorn interface to support a const sorted_list:
class sorted_list::iteratorn
{
public:
iteratorn();
~iteratorn();
iteratorn(const sorted_list& list);
const list_link* list_begin() const;
bool iterator_end() const;
void iterator_next();
int iterator_get_key() const;
double iterator_get_value() const;
private:
// You *should* make this `const` but it is not required.
sorted_list::list_link* current;
};
As you can see, the changes are rather minimal, but need to be applied in various places.
const + non-const iterators:
I applied changes here based on the fact that your iteratorn was currently only defining read-only operations on your sorted_list. If you want to support write access to allow changing the value stored in list nodes (never allow changing the key or you won't have a sorted list anymore), you should define two iterator classes. See the STL iterator interface for more details.
You're copying the list by value, so the local copy in list_print() destructs at end of scope. Pass it by const-reference instead.
This in turn means you will have to change your sorted_list to support working with const lists. In particular you need to have a function that returns a const iterator pointing to the beginning of the list:
sorted_list::const_iteratorn begin() const
{
// returns a const_iteratorn pointing at the beginning of this list
}
Notice you need a new kind of iterator: a const_iteratorn, which promises it won't change the list.
Then, inside print_list() initialize a const_iteratorn with the start iterator that sorted_list returns, by copy:
sorted_list::const_iteratorn s(list.begin());
Finally create a second iterator instance that initializes with an end iterator coming from a member function of sorted_list, similar to the begin() function. This will maintain the const-correctness in print_list().
sorted_list::const_iteratorn e(list.end());
while( s != e ) { // two iterators should be able to compare
// ...
s.iterator_next(); // consider ++s
}
Also, as André mentioned, the fact you don't have a proper copy-constructor and assignment operator is a severe issue. Make sure that copying a sorted_list means copying all its elements, so that the new object owns its own list of elements. Do recall the Rule of Three.