Making list of objects of class with function overloading - c++

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;

Related

Linked list containig different derived class objects in c++

How we can create a linked list which can contain a different class of object. for example, if a person is base class and it has student and teacher as a derived class so How I can create a linked list which can contain both classes of objects like student also and teacher also.
below I wrote the source code for that but it is not working.
#include<iostream>
#include<string>
using namespace std;
int classNum;
class person
{
public:
string name;
public:
person(string="");
void show_p_name();
};
class student:public person
{
public:
string s_name;
int rollnum;
public:
student(string="", string="", int=100);
void show_name();
};
class worker:public person
{
public:
string w_name;
int work_id;
public:
worker(string="", string="", int=200);
void show_name();
};
// person
person::person(string nm)
{
name = nm;
}
void person::show_p_name()
{
cout << "In person class name is: " << name << endl;
}
// student inheriate person
student::student(string nm, string snm, int rolln)
:person(nm)
{
s_name = snm;
rollnum = rolln;
}
void student::show_name()
{
cout << "In student class name is: " << s_name << endl;
}
// worker inheriate person
worker::worker(string nm, string wnm, int wid)
:person(nm)
{
w_name = wnm;
work_id = wid;
}
void worker::show_name()
{
cout << "In worker class name is: " << w_name << endl;
}
// structure declaration
struct Node
{
person *p;
struct Node *next;
};
struct Node* createNode()
{
struct Node *t;
t = new struct Node;
classNum++;
if(t == NULL)
{
cout << "Memory Not Allocated\n";
//exit(0);
}
else
{
return t;
}
}
void initLink(struct Node *n)
{
n->next = NULL; //Make next as NULL
}
void initNode(struct Node *temp)
{
if((classNum % 2) == 0)
{
/*
temp->p = new student;
static_cast<student*>(temp->p)->name = "person_s_sahil";
static_cast<student*>(temp->p)->s_name = "student_sahil";
static_cast<student*>(temp->p)->rollnum = 100;
temp->p = static_cast<student*>(temp->p);
*/
temp->p = new student();
temp->p->name = "person_s_sahil";
temp->p->s_name = "student_sahil";
temp->p->rollnum = 100;
}
else
{
/*
temp->p = new worker;
static_cast<worker*>(temp->p)->name = "person_w_sahil";
static_cast<worker*>(temp->p)->w_name = "worker_sahil";
static_cast<worker*>(temp->p)->work_id = 100;
temp->p = static_cast<worker*>(temp->p);
*/
temp->p = new worker()
temp->p->name = "person_w_sahil";
temp->p->w_name = "worker_sahil";
temp->p->work_id = 100;
}
}
void attachEnd(struct Node **hptr, struct Node *tn)
{
struct Node *cn;
if(*hptr == NULL) //if list is empty
{
*hptr = tn; //attach new node to head
}
else
{
cn = *hptr; //get first node call as currunt node
while(cn->next != NULL) //get last node
{
cn = cn->next;
}
cn->next = tn; //attach new node to next of last node
}
}
void traverse(struct Node *hptr)
{
struct Node *temp;
if(hptr == NULL)
{
cout << "List is empty\n";
}
else
{
temp = hptr;
while(temp != NULL)
{
temp->p->show_name();
temp = temp -> next;
}
}
}
main()
{
struct Node *head = NULL;
struct Node *temp;
temp = createNode();
initLink(temp);
initNode(temp);
attachEnd(&head, temp);
traverse(head);
// like that I want to create node and attach to linked list
}
Proper approach would be to create linked list of pointers to objects of type Person.
Then you will populate it with pointers to instances of classes Student and Teacher. You have to create it dynamically (new keyword)
And now magic comes with using of keyword virtual for method declaration in Person class. Check this in google c++ polymorphism and C++ virtual method
If you latter call virtual method on pointer to Person object it will call proper method from derived class.
Do not forget to call delete for each element in list at the end of usage (program). And for this you have to define virtual destructor in Person class
In your case you should define Person class like this
class person
{
public:
string name;
virtual ~person() {};
public:
person(string="");
virtual void show_name();
};
Or another approach could be to use dynamic_cast<>() but for this you need to enable it in compiler. It is called RTTI (runtime type information). With dynamic cast you can safely cast from Person to Student or Teacher. If dynamic cast is not able to do cast it will return nullptr. So you can check this value.
Slightly fixed code (for purpose of compile-ability):
void initNode(struct Node *temp)
{
if ((classNum % 2) == 0)
{
/*
temp->p = new student;
static_cast<student*>(temp->p)->name = "person_s_sahil";
static_cast<student*>(temp->p)->s_name = "student_sahil";
static_cast<student*>(temp->p)->rollnum = 100;
temp->p = static_cast<student*>(temp->p);
*/
auto s = new student();
temp->p = s;
temp->p->name = "person_s_sahil";
s->s_name = "student_sahil";
s->rollnum = 100;
}
else
{
/*
temp->p = new worker;
static_cast<worker*>(temp->p)->name = "person_w_sahil";
static_cast<worker*>(temp->p)->w_name = "worker_sahil";
static_cast<worker*>(temp->p)->work_id = 100;
temp->p = static_cast<worker*>(temp->p);
*/
auto p = new worker();
temp->p = p;
temp->p->name = "person_w_sahil";
p->w_name = "worker_sahil";
p->work_id = 100;
}
void traverse(struct Node *hptr)
{
struct Node *temp;
if (hptr == NULL)
{
cout << "List is empty\n";
}
else
{
temp = hptr;
while (temp != NULL)
{
temp->p->show_p_name();
temp = temp->next;
}
}
}
If you fix your code, it will work (at a glance).

a simple payroll system using linked list c++

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;

Creating objects with new in function and "this is nullptr" exception

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.

Singly Linked List using Arrays: It's crashing on run-time

Whats wrong with this code?
I am writing this code to implement singly linked list using arrays but its not working. Im using code::blocks and its crashing on run time. Please help.
I must have missed out on something when it was taught in the class. xD
#include<iostream>
#include<stdio.h>
using namespace std;
class Node
{
int data;
Node *next;
public:
Node(int n)
{
data=n;
next=NULL;
}
friend class List;
};
class List
{
Node *listptr;
public:
void create();
void display();
};
void List::create()
{
Node *temp;
int n, num;
cout << "Enter number of nodes:" << endl;
cin >> n;
cout << "/nEnter the data" << endl;
for(int i=0; i<n; i++)
{
cin >> num;
Node *new_node=new Node(num);
if(listptr==NULL)
listptr=temp=new_node;
else
{
temp->next=new_node;
temp=temp->next;
}
}
}
void List::display()
{
Node *temp=listptr;
while(temp!=NULL)
{
cout << temp->data << "->";
temp=temp->next;
}
}
main()
{
List l1;
l1.create();
l1.display();
}
listptr not initialized, you can initialize in constructor.
List() {
listptr = 0;
}
Class List should be
class List
{
Node *listptr;
public:
List() {
listptr = 0;
}
void create();
void display();
};
Try following piece of code -
First Creating Node
class ListElement
{
int data;
ListElement* next;
public:
void set_element(int item) { data = item; }
int get_value() { return data; }
friend class List;
};
Another class for further operation
class List
{
ListElement *Start, *Tail, *New;
public:
List() { Start = Tail = New = NULL; } // initialise all pointer value to NULL
void add_element(int element) {
// Create a new Node
New = new ListElement;
New->set_element(element);
New->next = NULL;
// adding value or linkig each node to each other
(Start == NULL) ? Start = New : Tail->next = New;
Tail = New;
}
// print the whole linked list
void print()
{
ListElement* Current = Start;
while (Current != NULL)
{
cout << Current->get_value() << endl;
Current = Current->next;
}
}
};
Main Function
int main()
{
List L;
int num_of_element, element;
cin >> num_of_element;
for (int i(0); i < num_of_element; i++) {
cin >> element;
L.add_element(element);
}
L.print();
}
Hope it'll work.

returning something from a linked list

Can anybody tell me why my main program is printing out 9460301 instead of 350?
I'm just trying to insert a struct as a single item into a linked list. The struct has atrributes x and y. I then wish to print out the x attribute of the struct in my linked list. I have a huge program written out, and I tried stripping it down on this post just to what's neccessary to view for this new issue that has arisen for me.
My chunk struct and Linkedlist class are as follows:
struct chunk{
int x;
int y;
};
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)
{
T emptyList;
return emptyList;
}
else
{
node* cur;
for(int i = 0; i<indx+1; i++)
{
if(cur->mNext == NULL)
{
cout << "Indx out of range. Deleting last item." << endl;
break;
}
cur = cur->mNext;
}
return cur->mPayload;
}
}
void mInsertHelper(node* blah, T data)
{
if(blah->mNext != NULL)
mInsertHelper(blah->mNext, data);
else
{
blah->mNext = new node(data);
blah->mNext->mNext = NULL;
}
}
void mInsert(T data)
{
if(mStart == NULL)
{
mStart = new node(data);
//mStart->mPayload = data;
}
else
mInsertHelper(mStart, data);
}
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;
}
}
};
And my main.cpp:
int main()
{
chunk head;
head.x = 350;
head.y = 600;
linkedList<chunk> p1Snake;
p1Snake.mInsert(head);
cout<<p1Snake.mReturnT(0).x<<endl;
}
You never initialise cur before iterating through it.
node* cur; // <-- UNINITIALISED!
for(int i = 0; i<indx+1; i++)
{
if(cur->mNext == NULL)
{
cout << "Indx out of range. Deleting last item." << endl;
break;
}
cur = cur->mNext;
}
return cur->mPayload;
That first line should be:
node* cur = mStart;
And I think you should use indx instead of indx+1 in that loop... Unless you were using a dummy-head scheme, which you're not.
The logic inside the loop for detecting out-of-bounds is a bit wrong, also. How about revamping the whole thing:
node* cur = mStart;
while( cur && indx > 0 ) {
cur = cur->mNext;
indx--;
}
if( !cur ) {
cout << "Indx out of range." << endl;
return T();
}
return cur->mPayload;