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

  • (2 Pages)
  • +
  • 1
  • 2

20 Replies - 755 Views - Last Post: 03 October 2012 - 08:54 AM Rate Topic: -----

#1 sseabass92  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 30-September 12

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.

Example of input and output:
Input:
4
2
Zapp
Leela
10 20
3
Dr.Zoidberg
Mom
14 28 30 18
4
Proff.Fansworth
Gunter
18 16 18 20 5
2
Fry
Nibbler
5 5

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:

/******************************************************
Author: 
Class: Data Structures 
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
    Package* next;  		   // points to next package of list
    float charge;              // 

    public:

        virtual ~Package(){}
   
        //Default constructor not sure if done right
        Package() : sender(""), receiver(""), length(0), width(0), next(NULL){}

        //Auxiliary constructor  to be used for inserting objects
        Package(string s, string r, int l, int w, Package* p) : sender(s),receiver(r),length(l),width(w),next(p){ }

        //These were supposed to insert the package type into the list of packages
        //I'm not sure how to create a link list of different objects
        virtual void insert_two(string s, string r, int l, int w){}
        virtual void insert_three(string s, string r, int l, int w, int h, int m){}
        virtual void insert_four(string s, string r, int l, int w, int h, int d, int m){}

        //Gets the sender and receiver data in a package
        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;}

        //supposed to be used to help locate packages with getAtPackage
        Package* getFirstPackage();
        
        //Used to locate packages in linked list
        Package* getAtPackage(int i);
};

Package* Package::getFirstPackage()
{
    Package* tmp;
    tmp = new Package(sender,receiver,length,width,next);
    return tmp;
}


Package* Package::getAtPackage(int i)
{	
    if(i == 0)
        return getFirstPackage();

    if(i == 1)
        return next;

    Package* p = next;
    int counter = 1; 

    while (p->next->next != NULL && counter < i)
    {
        counter++;
        p = p->next;
    }
    return p;
}


//-------------------------------------------
class two_D : public Package
{
    protected:
        int area;

    public:

    two_D(string s, string r, int l, int w, Package* p) : Package(s,r,l,w,p){}

    void insert_two(string s, string r, int l, int w)
    {
        two_D* tmp;
        tmp = new two_D(s,r,l,w,next);
        next = tmp;
    }

    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, Package* p, int h, int m) : two_D(s,r,l,w,p)
        {
            height = h;
            weight = m;
        }

        void insert_three(string s, string r, int l, int w, int h, int m)
       {
            Package* tmp;
            tmp = new three_D(s,r,l,w,next,h,m);
            next = tmp;
        }

        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, Package* p, int h, int m, int d) : three_D(s,r,l,w,p,h,m)
        {
            depth = d;
        }

        void insert_four(string s, string r, int l, int w, int h, int d, int m)
        {
            Package* tmp;
            tmp = new four_D(s,r,l,w,next,h,m,d);
            next = tmp;
        }

        float getCharge()
        {
            h_volume = volume * depth;
            charge = (h_volume*.01)+(weight*3.14)+42.42;
            return charge;
        }

};




/*********************************************************************
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()
{
    Package package_list; //Should be new list that all packages will be stored in
    Package* 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,sender,receiver,length,width;

       if (type == 2)
            package_list.insert_two(sender,receiver,length,width);
        else
        {
            cin>>height;

            if (type == 3)
            {
                cin>>weight;
                package_list.insert_three(sender,receiver,length,width,height,weight);
            }
            else
            {
                cin>>depth,weight;
                package_list.insert_four(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.getAtPackage(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, not sure if you can use p->get charge() directly in math operations.

        counter++;
    }

    cout<<"Total Profit = "<<totalprofit<<endl;
    cout<<"Average = "<<totalprofit/number<<endl;

    return 0;
} 


Is This A Good Question/Topic? 0
  • +

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

#2 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3576
  • View blog
  • Posts: 11,126
  • Joined: 05-May 12

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

Posted 30 September 2012 - 11:57 AM

First thing you need to do is separate the concept of the package from the concept of the list of packages. You are trying to combine the two with your Package class.

Presumably, you have already covered linked lists, so something like this looks familiar:
class Node
{
    int data;
    Node * next;
};

class NodeList
{
    Node * head;

    void Add(int data);   
};



For your assignment, just think of your data being a Package rather than an int.
Was This Post Helpful? 2
  • +
  • -

#3 sseabass92  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 30-September 12

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.


/******************************************************
Author: [i]mod: name removed[/i]
Class: CS151 Data Structures Section B
Date: 9/26/12
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

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..

Was This Post Helpful? 0
  • +
  • -

#4 sseabass92  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 30-September 12

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
Was This Post Helpful? 0
  • +
  • -

#5 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3576
  • View blog
  • Posts: 11,126
  • Joined: 05-May 12

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

Posted 30 September 2012 - 02:26 PM

Review your line 196 for inputting the values to be used. The comma operator does not read from cin.
Was This Post Helpful? 1
  • +
  • -

#6 sseabass92  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 30-September 12

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
Was This Post Helpful? 0
  • +
  • -

#7 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3576
  • View blog
  • Posts: 11,126
  • Joined: 05-May 12

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.
Was This Post Helpful? 0
  • +
  • -

#8 sseabass92  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 30-September 12

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

Posted 30 September 2012 - 04:45 PM


//creates new empty Node with next pointer pointing to nexts' location
Node* Node::getFirstNode()
{
    Node* tmp;
    tmp = new Node(data,next);
    next = tmp; //Changes next to point to what tmp did should be first node
    delete tmp; //deletes tmp
    return next;
}

Node* Node::getAtNode(int i)
{
    if(i == 0)
        return getFirstNode();

    if(i == 1)
        return next;

    int counter = 1;

    while (next->next != NULL && counter < i)
    {
        counter++;
        next = next->next; //updates next to point to what nexts' next originally did, should let me traverse through the list
    }
    return next;
}
void Node::add(Package data)
{
    Node* tmp;
    tmp = new Node(data, next);
    next = tmp;
    delete tmp;
}



Does this code help avoid memory leaks? It deletes any temporary nodes it creates.
Was This Post Helpful? 0
  • +
  • -

#9 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3576
  • View blog
  • Posts: 11,126
  • Joined: 05-May 12

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

Posted 30 September 2012 - 04:56 PM

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.
Was This Post Helpful? 0
  • +
  • -

#10 sseabass92  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 30-September 12

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

Posted 30 September 2012 - 05:08 PM

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.
Was This Post Helpful? 0
  • +
  • -

#11 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3576
  • View blog
  • Posts: 11,126
  • Joined: 05-May 12

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

Posted 30 September 2012 - 05:15 PM

If you have a working linked list, just use it. Never re-write code unless you really have to. Since that linked list takes a template parameter, you can pass the Package as the template parameter.
Was This Post Helpful? 1
  • +
  • -

#12 sseabass92  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 30-September 12

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:


#include <iostream>
#include <string>
#include "Node.h"

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){ }

        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;
        }

};



int main()
{
    LinkedList<Package> package_list; //Should be new list that all packages will be stored in
    LinkedList<Package>* 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.insert_front(two_D(sender,receiver,length,width));
        else
        {
            if (type == 3)
            {
                cin>>height;
                cin>>weight;
                package_list.insert_front(three_D(sender,receiver,length,width,height,weight));

            }
            else
            {
                cin>>height;
                cin>>depth;
                cin>>weight;
                package_list.insert_front(four_D(sender,receiver,length,width,height,depth,weight));
            }
        }
			
        counter++;
      
               
    }
    counter = 0;

    //In this loop I need functions to access the position at counter
    //and then get the appropriate values: sender,receiver, and the charge
    while ( counter < number)
    {
        cout<<"#"<<counter<<":"<<"  From "<<getsender()<<" to "<<getreceiver()<<endl;
        cout<<"$ "<<getcharge()<<endl;
        totalprofit = totalprofit + getcharge();//adds the charge from each package to total profit*/
        cout<<package_list.size();

        counter++;
    }

    cout<<"Total Profit = "<<totalprofit<<endl;
    cout<<"Average = "<<totalprofit/number<<endl;

    return 0;
}




Here is the LinkedList template I use:


#ifndef Node_H
#define Node_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

  LinkedList() : m_next(NULL) {}


  LinkedList(const T& x, LinkedList<T>* p) 
             : m_data(x), m_next(p) {}

  ~LinkedList() {}

  LinkedList<T>&  operator= (const LinkedList<T>& rhs);

  LinkedList(const LinkedList<T>& cpy);
  
  int size() const;

  LinkedList<T>* getFirstPtr();

  LinkedList<T>* getAtPtr(int i);

  T at(int i);

  void clear();

  void insert_front(const T& x);

  bool operator== (const LinkedList<T>& rhs) const;
};


//Insert Front Is Working
template <typename T>
void LinkedList<T>::insert_front(const T& x)
{
  LinkedList<T>* temp;
  temp = new LinkedList(m_data,m_next);
  m_data = x;
  m_next = temp;
}

//Get First Pointer is Working
template <typename T>
LinkedList<T>* LinkedList<T>::getFirstPtr()
{
  LinkedList<T>* tmp;
  tmp = new LinkedList(m_data,m_next);
  return tmp;
}


template <typename T>
LinkedList<T>* LinkedList<T>::getAtPtr(int i)
{
  if(i == 0)
    return getFirstPtr();

  if(i == 0)
    return m_next;

  LinkedList<T>* p = m_next;
  int counter = 1; //counter at 2 because it gives right ouput with 1st tester question

  while (p->m_next->m_next != NULL && counter < i)
  {
    counter++;
    p = p->m_next;
  }
  return p;
}

//Is working 
template <typename T>
T LinkedList<T>::at(int i)
{
  T x;
  x = getAtPtr(i)->m_data;
  return x;
}

//Size function is working
template <typename T>
int LinkedList<T>::size() const
{
  int size = 0;

  LinkedList* p;
  p = m_next;
  while (p != NULL)
  {
    p = p->m_next;
    size++;
  }

  return size;
}

//Working with ouput havent checked for memory leaks.
template <typename T>
void LinkedList<T>::clear()
{
  LinkedList* discard;
  while(m_next != NULL)
  {
    discard = m_next;
    m_next = discard -> m_next;
    delete discard;
  }
}

/*
//empty dont know how to implement
template <typename T>
LinkedList<T>::LinkedList(const LinkedList<T>& cpy)
{}


//Don't know how to create
template <typename T>
LinkedList<T>&  LinkedList<T>::operator=(const LinkedList<T>& rhs)
{
  if(*this == &rhs)
    return *this;
  clear();
  LinkedList<T> *rhsList;
  *rhsList = rhs.getFirstPtr();
  while(rhsList != NULL)
  {
    insert(m_data, rhsList);
    rhsList = rhsList -> m_next;
  }
}

}*/


#endif



So if I try to use a function to draw out the sender information from my LinkedList<Package> it tells me there is no member in it called sender.
Was This Post Helpful? 0
  • +
  • -

#13 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3576
  • View blog
  • Posts: 11,126
  • Joined: 05-May 12

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

Posted 30 September 2012 - 09:15 PM

You'll have to do something like package_list.getAtPtr(i)->getsender().
Was This Post Helpful? 0
  • +
  • -

#14 sseabass92  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 30-September 12

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

Posted 30 September 2012 - 09:58 PM

With the following code I am still getting the error message: no member named 'getsender' in 'LinkedList<Package>'
while ( counter < number)
    {
        p = package_list.getAtPtr(counter);
        cout<<"#"<<counter<<":"<<"  From "<<p->getsender()<<" to "<<p->getreceiver()<<endl;
        cout<<"#"<<counter<<":"<<"  From "<<<" to "<<endl;
        cout<<"$ "<<getcharge()<<endl;
        totalprofit = totalprofit + p->getcharge();

        counter++;
    }



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?
Was This Post Helpful? 0
  • +
  • -

#15 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3576
  • View blog
  • Posts: 11,126
  • Joined: 05-May 12

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

Posted 30 September 2012 - 10:02 PM

Shouldn't line 3, be
Package * p = package_list.getAtPtr(counter);
?
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2