Thread: Linked List Class failing:

  1. #16
    Registered User
    Join Date
    Jun 2013
    Posts
    56
    Quote Originally Posted by jocdrew21 View Post
    That was a good point so to ensure it was empty I added name.clear();
    I thought that objects were lost when the program ended. I might have misunderstood what you were talking about.

    If curr is not == null and curr is set to head I should be able to use the while loop correctly, right? However there is not way it can execute correctly if the user cannot input "name" first. Even after I cleared the string name I run into the same issue. I have a feeling once I figure this out I will be quite annoyed with myself.
    re-read line 18 that tabstop hinted at and think about what you are trying to do there, and what is actually being done there.

    also, line 17 will give you the wrong name. You are telling it to show the name of the next item in the list not the current item you are pointed to.

  2. #17
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499

    Code:
    cout<<"The current name is: "<<curr->next->Name<<endl;
    cout<<"Enter the new name: "<<name;
    I see the error on line 18 but that is not the reason why the program is failing, right? Line 17 gives me the wrong name? I wrote:
    Code:
    while(curr->next!= NULL && curr->next->Name != name)
    		{
    			curr=curr->next;
    		}
    


    I hope you guys don't think I am a complete idiot here.



  3. #18
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499
    Damnit sorry for being slow..... O man, the hint was there all a long. Check if it is NULL then I dereferenced it, ahhhhh it clicked....

  4. #19
    Registered User
    Join Date
    Jun 2013
    Posts
    56
    Code:
    cout<<"The current name is: "<<curr->next->Name<<endl;
    This line here

    Code:
    curr->next->Name
    This statement tells the program to follow currents next pointer to the next member in the list and then display THAT name when your line is reading to the user the current name.

    Also, post up a new copy of your program as it stands now with errors so we can see where its failing now.

  5. #20
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499
    Very sorry for the late response. I normally respond within an hour. I have redone a lot and will post the whole code. It is all working and now I am tweaking a few things. How is my design? What could be better?

    Code:
    #ifndef __addressList__
    #define __addressList__
    
    #include <iostream>
    #include <string>
    
    using namespace std;
    typedef struct node {
        string Name;
        string DOB;
        string address;
        string aniversary;
        node *next;
    } *nodePtr;
    
    class AddressBook {
    private:
        nodePtr head;
        nodePtr current;
        nodePtr temp;
        
    public:
        AddressBook();
        
        void Initialize();
        void userPromptStatement();
        void AddNode(nodePtr);
        void deleteName(string name);
        void EditNameOrDate();
        void PrintAddressBook();
        void GenBirthdayCards(string);
        void GenAnnCard(string);
        void ExitProgram();
        
    };
    
    #endif
    Code:
    #include <iostream>
    #include <string>
    #include "addressList.h"
    using namespace std;
    AddressBook::AddressBook(){
        
        head=NULL;
        current=NULL;
        temp=NULL;
        
    }
    
    void setAniversary(string);
    string getAniversary();
    void AddressBook::AddNode(nodePtr temp)
    {
        if (head != NULL) { //list is already made
            current = head; //makes current pointer point to head of the list
            
            while (current->next != NULL)
            {   //while the next of current is not at end
                current = current->next;     //advance to next node
            }
            
            current->next =new node;
            current->next->address=temp->address;
            current->next->aniversary=temp->aniversary;
            current->next->DOB=temp->DOB;
            current->next->Name=temp->Name;
            current->next->next=nullptr;
        }
        else
        {
            head = new node; //now head is the front of the list
      head->address=temp->address;
      head->aniversary=temp->aniversary;
      head->DOB=temp->aniversary;
      head->Name=temp->Name;
      head->next=nullptr;
        }
        
    }
    
    void AddressBook::deleteName(string name)
    {
    	if (!head) cout<<"The List is empty\n";
    	else
    	{
      nodePtr current=head;
      if (head->Name==name)
      {
       current=head->next;
       head=nullptr;
       delete head;
       head=current;
                cout<<"complete "<<name<<" has been deleted\n";
      }
      else
      {
       nodePtr temp=nullptr;
       current=head;
       bool found=false;
       while (current->next)
       {
        if (current->next->Name==name)
        {
         temp=current->next->next;
         delete current->next;
         current->next=temp;
         found=true;
                        cout<<"complete "<<name<<" has been deleted\n";
        }
       }
       if (!found) cout<<"The name "<<name<<" not found in the list\n";
      }
    	}
    }
    
    void AddressBook::PrintAddressBook()
    {
        current = head;
    	if (current==nullptr) cout<<"The list is empty\n";
        while (current != NULL) {
            cout<<"NAME: "<<current->Name<<endl;
            cout<<"ADDRESS: "<<current->address<<endl;
      cout<<"BIRTHDAY: "<<current->DOB<<endl;
            cout<<"ANNIVERSARY: "<<current->aniversary<<endl;
            cout<<"\n";
            current= current->next;
        }
        
        
    }
    void AddressBook::EditNameOrDate()
    {
    	if (!head) cout<<"The list is empty\n";
    	else
    	{
      cout<<"1. Edit Name: \n";
      cout<<"2. Edit Birthday: \n";
      cout<<"3. Edit Anniversary: \n";
      int input;
      cin>>input;
            
      if (input==1)
      {
       cout<<"Enter the name you want to edit: /n";
       nodePtr curr = head;
       string name;
       name.clear();
       cin.ignore();
       getline(cin,name,'\n');
       while(curr!= NULL && curr->Name != name)
       {
        curr=curr->next;
       }
       if (!curr) cout<<"The name "<<name<<" wasn't found\n";
       else
       {
        cout<<"The current name is: "<<curr->Name<<endl;
        cout<<"Enter the new name: ";
        name.clear();
        getline(cin,name,'\n');
        curr->Name=name;
        cout<<"The name has been successfully changed to "<<curr->Name<<endl;
                }
            }
            else if (input==2)
            {
                cout<<"Enter the Birthday you want to edit: ";
                string date;
                date.clear();
                cin.ignore();
                getline(cin,date,'\n');
                nodePtr curr=head;
                while(curr!=NULL && curr->DOB!=date)
                {
                    curr=curr->next;
                }
                if (!curr) cout<<"The date "<<date<<" wasn't found\n";
                cout<<"The current date is: "<<curr->DOB<<endl;
                cout<<"Enter the new name: \n";
                cin.clear();
                cin.ignore();
                getline(cin, date, '\n');
                curr->DOB=date;
                cout<<"The date has been successfully changed to "<<curr->DOB<<endl;
                
            }
            else if (input==3)
            {
                cout<<"Enter the Anniversary date you want to edit: ";
                string AnnDate;
                AnnDate.clear();
                cin.ignore();
                getline(cin,AnnDate,'\n');
                nodePtr curr=head;
                while(curr->next!=NULL && curr->next->aniversary!=AnnDate)
                {
                    curr=curr->next;
                }
                cout<<"The current name is: "<<curr->next->aniversary<<endl;
                cout<<"Enter the new name: \n";
                AnnDate.clear();
                cin.ignore();
                getline(cin,AnnDate,'\n');
                curr->aniversary=AnnDate;
                cout<<"The name has been successfully changed to "<<curr->aniversary<<endl;
                
            }
    	}
    }
    void AddressBook::GenBirthdayCards(string birthdayBoy)
    {
        cout<<"Dear "<<birthdayBoy<<"\n\n";
        
        cout<<"Hope your birthday is really wonderful and this coming year is the best yet!\n";
        cout<<endl<<endl;
        cout<<"Love,\n";
        cout<<"Joanne\n";
        
    }
    
    void AddressBook::GenAnnCard(string happyCouple)
    {
        cout<<"Dear "<<happyCouple<<endl;
        cout<<endl<<endl;
        cout<<"May your anniversary be the best yet and we wish you more to come\n";
        cout<<endl<<endl;
        cout<<"Love,\n";
        cout<<"Joanna\n";
        
    }
    void AddressBook::userPromptStatement()
    {
        cout<<"Enter 1 to add a new contact"<<endl;
        cout<<"Enter 2 to delete a contect"<<endl;
        cout<<"Enter 3 edit a contect"<<endl;
        cout<<"Enter 4 to print your address book"<<endl;
        cout<<"Enter 5 to generate birthday cards"<<endl;
        cout<<"Enter 6 to generate anniversary cards"<<endl;
        cout<<"Enter 7 to exit the program"<<endl;
        
    }
    
    void AddressBook::ExitProgram()
    {
        
        EXIT_SUCCESS;
        
    }
    Code:
    #include <iostream>
    #include <string>
    #include "addressList.h"
    
    using namespace std;
    
    
    int main()
    {
        
        AddressBook MyAddressBook;
        MyAddressBook.userPromptStatement();
        
        int userInput;
    	nodePtr temp=new node;
        
    	string NAME;
    	while(1)
    	{
      cin>>userInput;
        
            if (!(cin>>NAME)) {
                cerr<<"Only enter integers, please\n\n";
                cin.clear();
                cin.ignore(numeric_limits<streamsize>::max(),'\n'); //prevents a never ending loop
                MyAddressBook.userPromptStatement();
            }
            
      switch (userInput) {
       case 1:
        cout<<"NAME: ";
        cin.ignore();
        getline(cin,temp->Name,'\n');
        cout<<"\nBIRTHDAY: ";
        getline(cin,temp->DOB,'\n');
        cout<<"\nADDRESS: ";
        getline(cin,temp->address,'\n');
        cout<<"\nANIVERSARY DATE: ";
        getline(cin,temp->aniversary,'\n');
        MyAddressBook.AddNode(temp);
        MyAddressBook.userPromptStatement();
        break;
       case 2:
        cout<<"Which contact would you like to delete?\n";
        cin.ignore();
        getline(cin, temp->Name, '\n');
        MyAddressBook.deleteName(temp->Name);
        MyAddressBook.userPromptStatement();
        break;
       case 3:
        MyAddressBook.EditNameOrDate();
                    MyAddressBook.userPromptStatement();
        break;
       case 4:
        MyAddressBook.PrintAddressBook();
        MyAddressBook.userPromptStatement();
        break;
                case 5:
        cout<<"Who would you like to send a Birthday card too?\n";
        getline(cin, temp->Name, '\n');
        MyAddressBook.GenBirthdayCards(NAME);
        MyAddressBook.userPromptStatement();
        break;
                case 6:
        cout<<"Who would you like to send a anniversary card too?\n";
        getline(cin, temp->Name, '\n');
        MyAddressBook.GenAnnCard(NAME);
        MyAddressBook.userPromptStatement();
        break;
                    
                case 7:
        MyAddressBook.ExitProgram();
        break;
                
       default:
        break;
                    
                   
      }
    	}
        return 0;
    }
    How would I use list?
    Code:
    struct addressBook
    {
        std::string name;
        std::string age;
        std::string streetAddress;
        
    };
    
    class MyAddressBook {
    private:
        std::list<addressBook> Myaddress;
        
    
    public:
        MyAddressBook();
        ~MyAddressBook();
        
        void addContact(std::string);
        void deleteContact();
    };
    Would I just push data into it and everything is done? I just found this one and after reading and reading online and watching youtube. I cannot see how to use it like I used it above. Can anyone shed some light on that one for me.

    In my other code I am having an issue with the if statement in the main.cpp. I wanted to check if the user entered a char and if so throw an error. It works however the user has to enter an int twice before the list of requests shows up. So if I want to enter a new contact I have to enter 1, twice. It is an annoying flaw that I would like to fix. Any advice?

  6. #21
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    How is my design? What could be better?
    You'll forgive me for not taking too close of a look I hope.

    One stark error is that there is no destructor for your address book.
    Code:
    void AddressBook::cleanup() {
       NodePtr next;
       for (NodePtr walk = head; walk != NULL; walk = next) {
          next = walk->next;
          delete walk;
       }
    }
    
    AddressBook::~AddressBook() {
       cleanup();
    }
    Also it can be important to restrict the scope of things that only AddressBooks are meant to use:

    Code:
    class AddressBook {
    private:
       struct node {
        string Name;
        string DOB;
        string address;
        string aniversary;
        node *next;
    };
    
    // more private things...
    
    public:
       typedef struct node *NodePtr;
    // ...
    };
    If you want even more commentary, well, I'm not sure how much to give you, so don't feel overwhelmed by what I'm about to say. The one reason I don't like making list classes is if you want to get something that you can use in a lot of situations (and not depend on std::list for some reason), it's a lot of work. Your address book class is one kind of address book. A user might want to have different address books with different fields for instance. It also works with cout and cin, which makes it impossible to use in some other way, like in a batch program, or in a GUI. That is, your address book is highly user interactive and interactive in a particular way, but I'm not convinced that it needs to be.

    I also tend to be very uncreative when I make my own lists. I tend to echo the standard's design in some way, just because the iterator pattern is so safe and (in my opinion) it makes list classes easier to implement.

    Would I just push data into it and everything is done? I just found this one and after reading and reading online and watching youtube. I cannot see how to use it like I used it above. Can anyone shed some light on that one for me.
    Well, I thought we had a tutorial on std::list but it turns out we do not. At least I can't find one.

    Anyway, I think there are three big things to know. First, the data that you want to store in the list is all that you need to design.
    Code:
     struct ContactEntry {
        string Name;
        string DOB;
        string address;
        string aniversary;
        ContactEntry( string inName, inDOB, inAddress, inAniv): 
           name(inName), DOB(inDOB), inAddress(inAddress), aniversary(inAniv) {} 
    };
    
    int main() {
       std::list<ContactEntry> addressBook;
       // ...
    }
    You can also design a proper class to represent the data, which might be appropriate, especially when the data is not a group of other objects. The data defines what kind of list it is. Then you can push data onto the front or back of the list:
    Code:
    ContactEntry joe( "John Doe", "19640312", "123 Main St, Anywhere, US 90210", "" );
    ContactEntry ann( "Ann Jones", "19870416", "404 Web Rd, Nowhere, US 50321", "" );
    addressBook.push_front( joe );
    addressBook.push_back( ann );
    This is just scratching the tip of the ice berg though.

    The final thing is that in order to access elements, you will use iterators (or the range based for loop, if there is C++11 compatibility).
    Code:
    for (std::list<ContactEntry>::iterator i = addressBook.begin(); i != addressBook.end(); i++) { 
       // do something with i
    }
    i is basically like a pointer, so if you wanted to use a member function of the data object, then you would call it using the arrow syntax.

    There is a point to studying the iterator pattern in itself, since there are different kinds with different capabilities. List uses the bidirectional kind. See Iterators.

    That's pretty much the basics! Don't be afraid of the reference. It will explain everything about std::list, and more importantly, everything I glossed over.
    Last edited by whiteflags; 12-24-2013 at 03:02 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Splitting in a linked list class
    By FloatingButter in forum C++ Programming
    Replies: 14
    Last Post: 03-17-2013, 08:59 AM
  2. Linked list of a class object?....
    By chadsxe in forum C++ Programming
    Replies: 6
    Last Post: 12-08-2005, 03:15 PM
  3. Basic Linked List class
    By ExCoder01 in forum C++ Programming
    Replies: 3
    Last Post: 09-14-2003, 02:15 AM
  4. traversing a linked list with a node and list class
    By brianptodd in forum C++ Programming
    Replies: 2
    Last Post: 04-24-2003, 11:57 AM
  5. STL Linked List of class within class
    By NixPhoeni in forum C++ Programming
    Replies: 3
    Last Post: 11-30-2001, 10:17 AM