How do I add objects of different types to a Linked List C++

Posted 30 September 2012 - 11:31 AM

I am asked to create a program using polymorphism, inheritance, and virtual functions. The first line of the input gives the number of packages P.
The 2nd line is an integer stating the number of dimensions, followed by 2 strings: a sender, and receiver. Then, according to the number of dimensions of the package, the respective measurements of each dimension of the package. and finally, for 3D and 4D packages, a weight measure.

Output:
#0: From Zapp to Leela
$10.00
#1: From Dr.Zoidberg to Mom
$273.90
#2: From Proff.Fansworth to Gunter
$1094.92
#3: From Fry to Nibbler
$1.25

TOTAL PROFIT = $1380.07
AVERAGE = $345.01

We need to use a dynamically allocated data structure to hold the packages and I chose a Linked List. However, I am having trouble with inserting objects of a different type into a linked list. Here is my code so far:

Re: How do I add objects of different types to a Linked List C++

Posted 30 September 2012 - 02:10 PM

Ok thank you very much for replying so quickly. This assignment was already due friday 9/30/12. I am just still working on it because I really want to understand it. I have made a new class Node in this new revision of my code. However, I didn't make a second NodeList class because we weren't taught to make linked lists that way. We did it with just the next pointer and data.

I think your suggested helped and it definitely makes sense that way. I am no longer getting a segfualt error which i think is progress. However, my output is not getting the values
I need from the package as expected.
This is my output now:
#0: From to
$ 0
#1: From to
$ 0
#2: From to
$ 0
#3: From to
$ 0
Total Profit = 0
Average = 0

Again thank you so much for your help I have been pouring hours into this but lack certain knowledge to make it work.

This post has been edited by modi123_1: 30 September 2012 - 02:38 PM
Reason for edit:: removed user's name and fixed botched code tags..

Re: How do I add objects of different types to a Linked List C++

Posted 30 September 2012 - 02:20 PM

EDIT: Now has code formatting
Ok thank you very much for replying so quickly. This assignment was already due friday 9/30/12. I am just still working on it because I really want to understand it. I have made a new class Node in this new revision of my code. However, I didn't make a second NodeList class because we weren't taught to make linked lists that way. We did it with just the next pointer and data.

/******************************************************
Author:
Class:
Date:
Description: This codes reads package descriptions
such as how many of what type (2D,3D, or 4D), who
sent them and to whom they are going. It also outputs
the charge, tallies a total, and calculates an average.
*******************************************************/
#include <iostream>
#include <string>
using namespace std;
//-------------------------------------------
class Package
{
protected:
int length, width; // All packages
string sender, receiver; // have these variables
float charge; // points to next package of list
public:
virtual ~Package(){}
Package() : sender(""), receiver(""), length(0), width(0){}
Package(string s, string r, int l, int w) : sender(s),receiver(r),length(l),width(w){ }
//Used to get the sender and receiver in packages
virtual string getsender(){return sender;}
virtual string getreceiver(){return receiver;}
//Used to get the charge for each package type in the list
virtual float getcharge(){return charge;}
};
//-------------------------------------------
class two_D : public Package
{
protected:
int area;
public:
two_D(string s, string r, int l, int w) : Package(s,r,l,w){}
float getCharge()
{
area = length * width;
charge = area * .05;
return charge;
}
};
//-------------------------------------------
class three_D : public two_D
{
protected:
int height, volume, weight;
public:
three_D(string s, string r, int l, int w, int h, int m) : two_D(s,r,l,w)
{
height = h;
weight = m;
}
float getCharge()
{
volume = area * height;
charge = (volume*.02)+(weight*2.15);
return charge;
}
};
//-------------------------------------------
class four_D : public three_D
{
private:
int depth, h_volume;
public:
four_D(string s, string r, int l, int w, int h, int m, int d) : three_D(s,r,l,w,h,m)
{
depth = d;
}
float getCharge()
{
h_volume = volume * depth;
charge = (h_volume*.01)+(weight*3.14)+42.42;
return charge;
}
};
//This is my new node class.
class Node : public Package
{
private:
Package data;
Node* next;
public:
Node() : next(NULL){}
Node(Package x,Node* p) : data(x), next(p){}
void add(Package data);
Node* getFirstNode();
Node* getAtNode(int i);
};
Node* Node::getFirstNode()
{
Node* tmp;
tmp = new Node(data,next);
return tmp;
}
Node* Node::getAtNode(int i)
{
if(i == 0)
return getFirstNode();
if(i == 1)
return next;
Node* p = next;
int counter = 1;
while (p->next->next != NULL && counter < i)
{
counter++;
p = p->next;
}
return p;
}
void Node::add(Package data)
{
Node* tmp;
tmp = new Node(data, next);
next = tmp;
//Do I need to delete tmp here?
}
/*********************************************************************
Inputs for main are designed to be read directly from a file.
I want the program to create a new empty package list and then
read the first input (number of packages).
Then a loop is created and runs for the number of packages there are.
The first part reads the type,sender,receiver,length, and width
since all packages have these values.
Next an if else series of statements is used to determine what to do
if a package is of a certain type.
If the type is 2 (2D) I wanted it to insert a package of type 2D
into the package list.
If it is 3 (3D) it reads in the height and weight and creates
a new package in the package list of type 3D.
If its is 4 (4D) it reads in height,depth, and weight and creates
a new package in the package list of type 4D.
However, I dont know create a list of different objects and so
can't properly construct a list of the packages.
******************************************************************/
int main()
{
Node package_list; //Should be new list that all packages will be stored in
Node* p; //Pointer to node used for performing operations on that node
//declares all the variables that are used to describe packages
int number,type,length,width,height,depth,weight, totalprofit = 0, average;
int counter = 0;
string sender, receiver;
cin>>number;
while ( counter < number )
{
cin>>type,sender,receiver,length,width;
if (type == 2)
package_list.add(two_D(sender,receiver,length,width)); //can the nodes be added in this way since my add function excepts objects of type package now?
else
{
cin>>height;
if (type == 3)
{
cin>>weight;
package_list.add(three_D(sender,receiver,length,width,height,weight));
}
else
{
cin>>depth,weight;
package_list.add(four_D(sender,receiver,length,width,height,depth,weight));
}
}
counter++;
}
counter = 0;
//This while loop is supposed to get the the package at the first position of the linked package list
//It is supposed to print out the position and then get the sender and receiver data from that list position
//It repeats this for all the packages using the first input (number).
while ( counter < number)
{
p = package_list.getAtNode(counter);
cout<<"#"<<counter<<":"<<" From "<<p->getsender()<<" to "<<p->getreceiver()<<endl;
cout<<"$ "<<p->getcharge()<<endl;
totalprofit = totalprofit + p->getcharge();//adds the charge from each package to total profit
counter++;
}
cout<<"Total Profit = "<<totalprofit<<endl;
cout<<"Average = "<<totalprofit/number<<endl;
return 0;
}

I think your suggested helped and it definitely makes sense that way. I am no longer getting a segfualt error which i think is progress. However, my output is not getting the values
I need from the package as expected.
This is my output now:
#0: From to
$ 0
#1: From to
$ 0
#2: From to
$ 0
#3: From to
$ 0
Total Profit = 0
Average = 0

Re: How do I add objects of different types to a Linked List C++

Posted 30 September 2012 - 02:49 PM

I have changed the following main to:

int main()
{
Node package_list; //Should be new list that all packages will be stored in
Node* p;
//declares all the variables that are used to describe packages
int number,type,length,width,height,depth,weight, totalprofit = 0, average;
int counter = 0;
string sender, receiver;
cin>>number;
while ( counter < number )
{
cin>>type;
cin>>sender;
cin>>receiver;
cin>>length;
cin>>width;
if (type == 2)
package_list.add(two_D(sender,receiver,length,width));
else
{
if (type == 3)
{
cin>>height;
cin>>weight;
package_list.add(three_D(sender,receiver,length,width,height,weight));
}
else
{
cin>>height;
cin>>depth;
cin>>weight;
package_list.add(four_D(sender,receiver,length,width,height,depth,weight));
}
}
counter++;
}
counter = 0;
//This while loop is supposed to get the the package at the first position of the linked package list
//It is supposed to print out the position and then get the sender and receiver data from that list position
//It repeats this for all the packages using the first input (number).
while ( counter < number)
{
p = package_list.getAtNode(counter);
cout<<"#"<<counter<<":"<<" From "<<p->getsender()<<" to "<<p->getreceiver()<<endl;
cout<<"$ "<<p->getcharge()<<endl;
totalprofit = totalprofit + p->getcharge();//adds the charge from each package to total profit
counter++;
}
cout<<"Total Profit = "<<totalprofit<<endl;
cout<<"Average = "<<totalprofit/number<<endl;
return 0;
}

I am still getting this as my output though.
#0: From to
$ 0
#1: From to
$ 0
#2: From to
$ 0
#3: From to
$ 0
Total Profit = 0
Average = 0

Re: How do I add objects of different types to a Linked List C++

Posted 30 September 2012 - 03:45 PM

You need to take a very careful look at how your linked list is implemented. There is some kind of mismatch between your add() code and your getNodeAt() code. Your add() code adds nodes pointed to by next, but your getNodeAt() code, assumes that the current instance is the first node and creates (and leaks) a pointer to a copy of the data.

Re: How do I add objects of different types to a Linked List C++

Now you are just setting yourself to access memory that has been freed. Your add() and getFirstNode() leave next pointing to memory that you deleted. It's time to review how your linked list works.

Did you learn the more common C-style linked list where you just have a pointer to the beginning of the list, or did you learn the Pascal style linked list where have a concrete instance of a node that holds a pointer to the head of the list? Right now it looks like you are trying to implement both.

Re: How do I add objects of different types to a Linked List C++

I'm not sure if this answers your question but in a previous assignment we were given a class like this:

/* @file: linkedlist.h
* Definition of templated class LinkedList
* Implementation of List A.D.T.
* @C - Omicron Persei 8 Grand Emperor Lrrr
*
* Version 3.14
*/
/* __________________
/ \
| LinkedList Class |
\__________________/
Purpose: Implements a List ADT using a dynamically allocated
linked list to store the elements of the list.
Design: This linked list implementation is designed to have a "sentinel"
node at the end of the list. The data element of the sentinel node
is left undefined.
Error Handling: Whenever a function is given invalid parameter values
the message "!-- ERROR : PANIC in LINKEDLIST!!" and maybe an explanation
is displayed. The list should remains unchanged.
If the function returns a value this value is undefined unless
otherwise specified by the function description.
*/
#ifndef LINKED_LIST_H
#define LINKED_LIST_H
#include <iostream>
template <class T>
class LinkedList
{
public:
T m_data; // Data to be stored
LinkedList<T>* m_next; // Pointer to the next element in the list
static T m_objerr;
// Purpose: Default constructor
// Postconditions: next pointer set to NULL
// -INLINE-
LinkedList() : m_next(NULL) {}
// Purpose: Auxiliaty constructor, construct from parameters
// useful when inserting elements
// Postconditions: data and next pointer set to parameters
// -INLINE-
LinkedList(const T& x, LinkedList<T>* p)
: m_data(x), m_next(p) {}
// --------
// ---- Big 3 Member Functions ---
// --------
// Purpose: Destructor
// IMPORTANT:: FOr didactic purposes, the destructor is left empty.
// YOU are expected to implement function clear() to de-allocate the list
~LinkedList() {}
// Purpose: performs a deep copy of the data from rhs into this linked list
// Parameters: rhs is linked list to be copied
// Returns: *this
// Postconditions: this list contains same data values (in the same order)
// as are in rhs; any memory previously used by this list has been
// deallocated.
LinkedList<T>& operator= (const LinkedList<T>& rhs);
// Purpose: copy constructor
// Parameters: cpy is the LinkedList that is to be copied
// Postconditions: this list contains same data values (in same order)
// as in cpy.
LinkedList(const LinkedList<T>& cpy);
// --------
// ---- Basic Accessor Operations ---
// --------
// Purpose: accessor function for the current # data values in the list
// Returns: current size of the list
int size() const;
// Purpose: determines whether the list is empty
// Returns: true if list is empty; otherwise, false
bool isEmpty() const;
// Purpose: Get a pointer to the first element node
// Returns: pointer to the first node in the list;
// returns NULL if the list is empty
LinkedList<T>* getFirstPtr();
// Purpose: accessor function for last element node
// Returns: pointer to the last element's node in the list;
// returns NULL if list is empty
LinkedList<T>* getLastPtr();
// Purpose: accessor function for a node in the list
// Returns: pointer to the node at the i'th position in the list;
// returns NULL if no such element exists.
LinkedList<T>* getAtPtr(int i);
// Purpose: accessor function for the first element of the list
// Returns: a copy of the first element of the list,
T first();
// Purpose: accessor function for the last element of the list
// Returns: a copy of the last element of the list,
T last();
// Purpose: accessor function for an element of the list
// Returns: a copy of the element at the i'th position in the list
T at(int i);
// --------
// ---- Basic Mutator Operations ---
// --------
// Purpose: effectively "empties" the list
// Postconditions: all dynamically allocated memory for nodes deallocated
void clear();
// Purpose: puts the data x in the front of the list
// Parameters: x is data value to inserted
// Postconditions: x is the first element of the list
void insert_front(const T& x);
// Purpose: puts the data value x in the list at position i
// Parameters: x is data value to inserted
// i position to insert x at.
// Postconditions: x is the ith element of the list
void insert(const T& x, int i);
// Purpose: puts the data value x in the position pointed by pos
// Parameters: x is data value to inserted
// pos pointer to the position to insert x at.
// Preconditions: pos is a pointer in this list.
// Postconditions: x is inserted at the position pointed by pos
void insert(const T& x, LinkedList<T>* pos);
// Purpose: removes the element at position i
// Parameters: i position of element to remove.
// Postconditions: the ith element of the list is removed
void remove(int i);
// Purpose: removed the element in the position pointed by pos
// Parameters: pos pointer to the position to remove.
// Preconditions: pos is a pointer in this list.
// Postconditions: position pointed by pos is removed from the list
void remove(LinkedList<T>* pos);
// --------
// ---- Complex Operations ---
// --------
// Purpose: determines whether this list is identical to rhs list in
// terms of data values and their order in the list
// Parameters: rhs is list to be compared to this list
// Returns: true if lists are identical; otherwise, false
bool operator== (const LinkedList<T>& rhs) const;
// Purpose: determines whether x is in the list
// Parameters: x is data value to be found
// Returns: a pointer to the position of x in the list;
// otherwise, NULL
LinkedList* find(const T& x);
// Purpose: removes all duplicates from the lost
// Postconditions: every element in the list occurs only once in the list
void purge();
// Purpose: appends two lists
// Parameters: xlist, a list to append to the end of 'this' list
// Postconditions: elements of alist are appended to 'this' list
void append(const LinkedList<T>& xlist);
}; // of class LinkedList
// Declaration of static member objerr
// used as a return value after PANIC messages
template <typename T>
T LinkedList<T>::m_objerr;
// --------------- Utility Function for Printing
// Purpose: prints a LinkedList
template <typename T>
std::ostream& operator<< (std::ostream& out, const Package& xlist)
{
out << "[ ";
const Package* p = &xlist;
while ( p->next != NULL ){
out << p->senderdata << ", ";
p = p->next;
}
out << "]";
return out;
}
#include "linkedlist.hpp"
#endif

We were asked to create the function definitions for this in another file and then use a tester.cpp file to test if we had the functions working properly. I was able to construct a list using the insert_front() function which had the same code as my original add() function I was trying to use for this current program that's why I thought it was right. I never did get the operator=(), or the copy constructor function to work though. I guess I just need to do a lot more reading.

Re: How do I add objects of different types to a Linked List C++

Posted 30 September 2012 - 07:06 PM

Ok so I recreated the main program using the linked list template. I believe I am properly inserting nodes because I used a size function and it returned 4 which is the amount of objects I am putting into the list. The functions in my linked list were working with a previous tester so I think they are correct except for maybe memory leaks I am unaware of. Now I don't know how to get the specific data out of the nodes that I want. I need the sender, receiver, and the charge calculated on the package.
Here is my main program:

Since my Package function has the virtual functions: get sender(), get receiver(), and getcharge() and LinkedList is of type package it should be able to find them right? Would this mean that the nodes are being created but not in the right way? Or is LinkedList<Package> of a different type then just Package so it cant use those function members?