Linked List Issues:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#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 userPromptStatement();
    void AddNode(nodePtr);
    void deleteName(string);
    void EditNameOrDate();
    void PrintAddressBook();
    void GenBirthdayCards(string);
    void GenAnnCard(string);
    void ExitProgram();
    
};

#endif 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#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 Delname)
{
    //nodePtr delPtr = NULL;
    temp = head;
    current=head;
    
	while (current != NULL && current->Name != Delname)
	{
        temp = current;
        current=current->next;
    }
    if (current == NULL) {
        cout<<Delname<<"Was not in the list\n";
    }
    else{
		temp->next=current->next;
        delete current;
        cout<<"Name: "<< Delname <<" was deleted.\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()
{
	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;
        
        if (curr==NULL) {
            cout<<"Error, list is empty"<<endl;
        }
        string name;
        name.clear();
		getline(cin,name,'\n');
        
		while(curr->next!= NULL && curr->next->Name != name)
		{
			curr=curr->next;
		}
        
		cout<<"The current name is: "<<curr->next->Name<<endl;
		cout<<"Enter the new name: "<<name;
		curr->next->Name=name;
		cout<<"The name has been successfully changed to "<<curr->next->Name<<endl;
        
        }
	
	else if (input==2)
	{
        cout<<"Enter the Birthday you want to edit: ";
		string date;
		getline(cin,date,'\n');
		nodePtr curr=head;
		while(curr->next!=NULL && curr->next->DOB!=date)
		{
			curr=curr->next;
		}
		cout<<"The current name is: "<<curr->next->DOB<<endl;
		cout<<"Enter the new name: "<<date;
		curr->next->DOB=date;
		cout<<"The name has been successfully changed to "<<curr->next->DOB<<endl;
    
	}
    else if (input==3)
	{
        cout<<"Enter the Anniversary date you want to edit: ";
		string AnnDate;
		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: "<<AnnDate;
		curr->next->aniversary=AnnDate;
		cout<<"The name has been successfully changed to "<<curr->next->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;
    
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <iostream>
#include <string>
#include "addressList.h"

using namespace std;


int main()
{
    
    AddressBook MyAddressBook;
    int userInput;
    //string NAME, BIRTHDAY, ADDY, NEWANIVERSARY;
	nodePtr temp=new node;
    MyAddressBook.userPromptStatement();
	string NAME;
	while(1)
	{
		cin>>userInput;
        
		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>>NAME;
                
				MyAddressBook.deleteName(NAME);
				MyAddressBook.userPromptStatement();
				break;
			case 3:
				MyAddressBook.EditNameOrDate();  //need help here
				break;
			case 4:
				MyAddressBook.PrintAddressBook();
				MyAddressBook.userPromptStatement();
				break;
            case 5:
				cout<<"Who would you like to send a Birthday card too?\n";
				cin>>NAME;
				MyAddressBook.GenBirthdayCards(NAME);
				MyAddressBook.userPromptStatement();
				break;
            case 6:
				cout<<"Who would you like to send a anniversary card too?\n";
				cin>>NAME;
				MyAddressBook.GenAnnCard(NAME);
				MyAddressBook.userPromptStatement();
				break;
                
            case 7:
				MyAddressBook.ExitProgram();
				break;
			default:
				break;
		}
	}
    return 0;
}

The errors are:
Lets say I enter Number 3 to edit a contact line 99 comes up with an error "Thread 1: EXE_BAD_ACCESS (code=1,address=0x60)". I do not even know what that means.

Delete Contact also is giving me errors. I am can't seem to see the error. The while loop on 99, 114, 130. I get the following error when I try to delete a name:
Linked Lists(5607,0x7fff73e1d310) malloc: *** error for object 0x100103b40: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Last edited on
Try using a debugger to see the status of variables and such when the errors occur.
I did but something is not clicking. I put the errors above. It seems to be skipping line 99 when I try to edit a name. I thought something was stored in there so I cleared it. However it jump right to the while loop and fails. This has be puzzled.
http://www.cplusplus.com/forum/general/112111/

Your searches in EditNameOrDate() bypass the first element

Also, you should limit the scope of your variables. There is no good reason for `temp' and `current' to be members of the class.

1
2
3
4
5
6
		head = new node; //now head is the front of the list
		head->address=temp->address;
		head->aniversary=temp->aniversary;
		head->DOB=temp->aniversary; //┬┐ever heard of a copy constructor? it would avoid these kind of mistakes
		head->Name=temp->Name;
		head->next=nullptr;
Last edited on
I used temp because I was planning on using it as that, temporary and deleting it.
Are you saying my issue is actually in the .h file when I used:
1
2
3
nodePtr head;
    nodePtr current;
    nodePtr temp;


Now I am starting to get very confused. I did use a constructor:
1
2
3
4
5
6
7
AddressBook::AddressBook(){
    
    head=NULL;
    current=NULL;
    temp=NULL;
    
}


Why not make temp and current apart of the class? I need them for when I delete something so that I can attach the list again.
Last edited on
When you need it, create it. It's a lot easier than trying to maintain the invariant. (it would be like using global variables)


> Are you saying my issue is actually in the .h file when I used:
No, I'm saying that that's bad design.


You've got an issue with your searches
while(curr->next!=NULL && curr->next->DOB!=date) may end because `cur->next' is NULL, and later you dereference it.
OK I see what you are saying.... How would you design it?
1
2
3
4
5
6
7
8
9
10
11
struct node{
    string Name;
    string DOB;
    string address;
    string aniversary;
    //node *next;
};

class AddressBook {
private:
   std::list<node> list; //or another container 


If you question was about how to design the linked list, I would use an empty header cell (no pointer) and make it circular, so all the pointers point to a cell and there is no need to threat `header' different.

But your approach works too, simply limit the scope of your variables.


You need to check at the start of the search
- if `head' is NULL
- if `head' has the element that you are searching for

Then you need to consider the case where the search fails (`curr->next' is NULL)
Only a few changes here. I removed the string arguments to the methods that had then as the temp node can be used for that
I added an initialize method, a ProcessInput method and a destructor. I also capitalized several names for consistency.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#ifndef __addressList__
#define __addressList__

#include <iostream>
#include <string>
#include <cstdlib>

using namespace std;

class AddressBook
{
private:
  typedef struct node {
    string Name;
    string DOB;
    string Address;
    string Aniversary;
    struct node *next;
  } *nodePtr;

  nodePtr head;
  nodePtr current;
  nodePtr temp;

  void AddNode(nodePtr);
  void DeleteName();
  void EditNameOrDate();
  void PrintAddressBook();
  void GenBirthdayCards();
  void GenAnnCard();
  void ExitProgram();
public:
  AddressBook();

  void Initialize();
  void ProcessInput();
  void UserPromptStatement();
  ~AddressBook();
};

#endif // __addressList__ 


The main method has been simplified and the user input placed in a ProcessInput file (and method)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include "AddressList.h"

using namespace std;

int main()
{
  AddressBook AdrBk;

  AdrBk.Initialize();
  AdrBk.ProcessInput();
}

AddressBook::AddressBook()
{
  // Create class object
}

AddressBook::~AddressBook()
{
  // Delete class object
  delete temp;
}

void AddressBook::ExitProgram()
{
  EXIT_SUCCESS;
}


The AddNode method has been simplified somewhat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "AddressList.h"

void AddressBook::AddNode(nodePtr current)
{
  nodePtr hold = new node;

  current = NULL;
  if(head) {
    current = head;
    while(current)
    {
      hold = current;
      current = current->next;
    }
    current = hold->next = new node;
  } else {
    current = head = new node;
  }
  current->next = NULL;

  current->Address = temp->Address;
  current->Aniversary = temp->Aniversary;
  current->DOB = temp->DOB;
  current->Name = temp->Name;
}


You forgot to update the next link of the node just before the one deleted, I added that in the delete name method

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
include "AddressList.h"

void AddressBook::DeleteName()
{
  nodePtr Hold = new node;
  Hold = head;

  if(head) {
    current = head;
    while(current) {
      if(current->Name == temp->Name) {
          Hold->next = current->next;
          delete current;
          cout<<"Name: "<< temp->Name <<" was deleted.\n";
          break;
      }
      Hold = current;
      current = current->next;
    }
  }
  if(head == NULL || current == NULL)
    cout<<temp->Name<<"Was not in the list\n";
}


The Initialize method
1
2
3
4
5
6
7
8
#include "AddressList.h"

void AddressBook::Initialize()
{
  temp = new node;
  head = NULL;
  current = NULL;
}


ProcessInput Looks pretty much the same except for the removal of string arguments

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include "AddressList.h"

void AddressBook::ProcessInput()
{
  string NAME;
  int userInput;

	while(1)
	{
		cin>>userInput;

		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');
				AddNode(temp);
				UserPromptStatement();
				break;
			case 2:
				cout<<"Which contact would you like to delete?\n";
				getline(cin,temp->Name,'\n');
				DeleteName();
				UserPromptStatement();
				break;
			case 3:
				EditNameOrDate();  //need help here
				break;
			case 4:
				PrintAddressBook();
				UserPromptStatement();
				break;
      case 5:
				cout<<"Who would you like to send a Birthday card too?\n";
				getline(cin,temp->Name,'\n');
				GenBirthdayCards();
				UserPromptStatement();
				break;
      case 6:
				cout<<"Who would you like to send a anniversary card too?\n";
				getline(cin,temp->Name,'\n');
				GenAnnCard();
				UserPromptStatement();
				break;
      case 7:
				ExitProgram();
				break;
			default:
				break;
		}
	}
}


Get Annaversary cards would look like

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "AddressList.h"

void AddressBook::GenAnnCard()
{
  current = head;
  while(current && (current->Name != temp->Name) && (current->Aniversary != temp->Aniversary)) {
      current++;
  }
  if(current) {
    cout<<"Dear "<<temp->Name<<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";
  }
}


The other functions basicaly the same.

You still have the situation where there will be identical names. I suggest that you add a 16 bit hash code to your node typedef. the structure is so small that woud could add all fields ti get a unique code.
When searching for a particular person, you could bring up the names and street where they lived and have the user select the proper one.

Hope ypu find this helpful.

Largins
Largin:
Thank you very much. Some of your methods look cleaner then mine. I forgot all about a destructor too so thanks again. I also like how to put the struct in the class and not global. I suppose that is a better way, and safer. How you did the generation of the cards was a nice touch. I had to double take for a second when I looked at it. I am going to do some more work on this program but using <list> has me intrigued and confused.

ne555:
I have never really worked with <list> before besides pushing a data into it and iterating through it to print it off. Would I just need the list like you wrote it and head in the private and have head equal the list? I started to look into that way and found more questions. Could you clear this up or me?

Topic archived. No new replies allowed.