how do you search for a lastname in a linked list? c++
i have a linked list that stores firstname, lastname, and phone number. i need to find the lastname
Are you using the STL?
I am using visual studio c++
Did you implement the linked list yourself?
i did. ammm can you give me an example of a referenced variable?
Referenced variable is like a pointer that is pretending to be deferenced.
Okay I need to know what your code is like first of all.
bool PhoneBook::Lookup (const string& lname, const string& fname, string& pnum) const { PhoneBookItem* p = head; PhoneBookItem* q = head->next; if (head == NULL) return false; else if (lname == p->lastname) { if (fname == p->firstname) { return true; } else return false; } else { while (q != NULL && lname != q->lastname) { p = q; } if (q != NULL && lname == q->lastname) if (fname == q->firstname) return true; else return false; else return false; } }
It says that the pnum should be returned to the calling function via a third argument, a reference variable. I don't know how. can you help me with this?
What is pnum supposed to be?
wio..phone number
All you need to do is assign pnum to the pnum of the node with the correct name.
``` while (q != NULL && lname != q->lastname) { p = q; } ``` This code doesn't make sense. You should try something like: ``` while (q != NULL && lname != q->lastname) { p = q; q = q->next; } ``` You need to update q and p.
So assuming you find it, before you return true, you wanna assign pnum. ``` if (fname == p->firstname) { pnum = q->pnum; // put it here return true; } ``` ``` if (fname == q->firstname) { pnum = q->pnum; // here too return true; } else ```
I tried that, but it doesn't work. Here is the code in the main. void LookupEntry(const PhoneBook& pb) { string last, first, phone; cout << "Enter last name: "; cin >> last; cout << "Enter first name: "; cin >> first; bool success = pb.Lookup(last, first, phone); if (success) { cout << "\nThe phone number is " << phone << ". \n"; } else { cout << "\nError: no one by this name is in the phone book.\n"; } }
``` string last, first, phone; ``` The problem is that `phone` should be a reference. ``` string last, first; string& phone; ```
Does it even compile?
It does, but that code in the main cannot be changed since our professor said so.
Okay, what sort of output are you getting? What is happening?
It outputs : Error: no one by this name is in the phone book. ================================================= if (success) { cout << "\nThe phone number is " << phone << ". \n"; } else { cout << "\nError: no one by this name is in the phone book.\n"; }
Alright, are you searching for something that is in the list?
yes
``` else if (lname == p->lastname) { if (fname == p->firstname) { return true; } else return false; } ``` This code is wrong. If the last name is correct but the first name is not correct, it should continue searching, but your code instead gives up entirely.
``` else if (lname == p->lastname && fname == p->firstname) { return true; } ``` This is what you should be doing.
There are a lot of bugs in your code, it'd be easier to show the correct way...
For example, why have `p` and `q`? You only need one to keep track of where you are, right?
yeah but i need to test this ============================================= if (head == NULL) return false; else if (lname == p->lastname && fname == p->firstname) { p->phone = head->phone; return true; } else { while (q != NULL && lname != q->lastname) { p = q; p = p->next; } if (q != NULL && lname == q->lastname && fname == q->firstname) { q->phone = head->phone; return true; } else return false; } ===================================== else { while (q != NULL && lname != q->lastname) { p = q; p = p->next; } if (q != NULL && lname == q->lastname && fname == q->firstname) { q->phone = head->phone; return true; } else return false; }
why are you setting `p->phone` to `head->phone`?
those are the variable in my struct ====================================================== struct PhoneBookItem { string lastname; string firstname; string phone; PhoneBookItem* next; PhoneBookItem(const string& l, const string& f, const string& ph); };
Yeah, but you're setting the current item `p` to have the same phone number as the first item `head`. There is no reason to do that.
Okay, you should start out with your current item point to the front: ``` PhoneBookItem* current = head; ```
yes i did that
If you go through the whole list without finding it, then you want to return false. ``` while (current != NULL) { // search code here current = current->next } return false; ```
Does that loop make sense so far? @Lynncake
yes it does, i'm writing the rest of it. but i am not sure if this is right
PhoneBookItem* p = head; if (head == NULL) return false; else { while (p != NULL) { if (lname == p->lastname && fname == p->firstname) { return true; } p = p->next; } return false; }
Now, for the search code... we just check if the names are correct ``` if (current->firstname == fname && current->lastname == lname) { pnum = current->phone; return true; } ```
We don't have anything if the names don't match. The loop will take care of that for us.
yes it worked! thank you
One second though.
``` if (head == NULL) return false; else { while (p != NULL) ``` The `if (head == NULL)` here is pointless. The `while (p != NULL)` already check if `head` is `NULL`.
@Lynncake Does that make sense?
yes, it does thanks a lot
alright, well good luck then.
for the delete, is this right? ====================================== PhoneBookItem* p = head; while (p != NULL) { if (lname == p->lastname && fname == p->firstname) { delete p; p->next=NULL; num--; return true; } p = p->next; } return false; ====================================== I followed your method/concept.
The problem with this is that you need to keep track of the item before you.
And you set the guy behind you's `next` property to your own `next` property.
so in here i should hava another pointer that points to the next element?
This case is a bit tricky because you have two case: 1) They are deleting the head... 2) They are deleting something in the middle of the list
For 1) you delete it, and set head to NULL For 2) you need to set the previous guy's next to the deleted guy's next
``` PhoneBookItem* last = head; PhoneBookItem* current = head->next; // Check head // Check guys in the middle of the list ```
For check head, we wanna do: ``` if (head != NULL && head->firstname == fname && head->lastname == lname) { delete head; head = NULL; } ```
For checking others, we want a loop: ``` while (current != NULL) { \\ check current last = current; current = current->next; } return false; ```
For current, we do something similar to head, but with a change: ``` if (current->firstname == fname && current->lastname == lname) { last->next = current->next; delete head; return true; } ```
Hmmm, there should be a `return true;` in the check head part too.
What we are doing is changing this: |dw:1364256150764:dw|
so the last is the head?
To this: |dw:1364256188626:dw|
Join our real-time social learning platform and learn together with your friends!