In this function (part of a bigger contact book program I am working on) it displays an item in a linked list, or in my case a contact. I would like to get the position of this item in the linked list, in order to delete the contact and add it back to the linked list.
void display_contact(std::string first, std::string last)
{
bool found;
node *curr = head;
found = false;
while (curr != NULL & !found)
{
if (curr->firstName == first)
{
found = true;
}
else if (curr->lastName == last)
{
found = true;
}
else
{
curr = curr->next;
}
}
if (found)
{
std::cout << "First Name: " << curr->firstName << "\n";
std::cout << "Last Name: " << curr->lastName << "\n";
std::cout << "Phone Number: " << curr->phoneNumber << "\n";
std::cout << "Editing contacts is coming soon.\n";
}
else
{
std::cout << "\n" << first << " " << last << " was not found.\n";
}
}
The actual result I get right now is just the contact information (Variables from the linked list)
node *curr = head;
found = false;
int idx = -1;
while (curr != NULL & !found)
{
idx++;
....
}
if found idx has the index
Related
Given the name of a node, this function should search the linked list; if its found inside, then return a pointer that points to that node, otherwise return null. Note: I am certain I have written this function successfully.
// getNode
Node *LinkedList::getNode(string name)
{
Node *temp = head;
while (temp != NULL)
{
if (temp->name.compare(name) == 0)
return temp;
temp = temp->next;
}
return NULL;
}
Given a node, this function prints: teamName(winScore-loseScore) on screen. Examples: UCLA(25-13) or Texas A&M(31-25). Note: I am sure I have written this function successfully.
// printNode
void LinkedList::printNode(Node *node)
{
if (node == NULL)
return;
else {
cout << node->name << "(" << node->winScore;
cout << "-" << node->loseScore << ")";
}
}
Given a team name, this function is supposed to print all the nodes in its adjacency list one-by-one in the following format (NOTE: the following is just one example!) This is where I think I am wrong.
Missouri University beat: New Mexico(52-23), Salisbury (48-31), Virginia (34-9)
void LinkedList::printList(string name)
{
if (head == NULL)
cout << "\n Empty list" << endl;
else {
Node *temp = head;
while (temp != NULL)
{
cout << temp->name << " beat: " << temp->name << endl; // Is this right?
temp = temp->next;
}
}
}
I'm guessing that this is close to what you want:
void LinkedList::printList(string name)
{
// find the node for the name you supply
// (or else I don't understand why 'name' is supplied to this function)
Node *temp = getNode(name);
if (temp) { // node with name found
if (temp->next) { // there's at least one adjacent node
cout << temp->name << " beat: ";
while ((temp = temp->next) != nullptr) {
printNode(temp);
if (temp->next) cout << ", ";
};
cout << "\n";
} else { // no adjacent nodes
cout << temp->name << " did not beat anyone\n";
}
}
}
below is my current in-progress code converting a singly linked to a doubly linked list. I haven't touched the delete function yet. I've gotten insert in empty list, end of list, and beginning of list apparently working.
However nodes inserting in the middle seemingly fail to create a link to the previous node. My debugging lines I inserted seem to show both the n->next and n-> prev with the correct memory address, but when I go to reverseprint, any nodes inserted in the middle are missed and the links are gone. Where am I going wrong in regards to this?
Code below:
#include <iostream>
#include <string>
using namespace std;
// define a node for storage and linking
class node {
public:
string name;
node *next;
node *prev;
};
class linkedList {
public:
linkedList() :top(NULL) {}
bool empty() { return top == NULL; }
node *getTop() { return top; }
node *getEnd() { return end; }
void setTop(node *n) { top = n; }
void setEnd(node *p) { end = p; }
void add(string);
int menu();
void remove(string);
~linkedList();
void reversePrint();
friend ostream& operator << (ostream&, const linkedList&); // default output is in-order print.
private:
node *top;
node *end;
};
void main() {
linkedList l;
cout << l.empty() << endl;
int option = 0;
string s;
bool go = true;
while (go) {
option = l.menu();
switch (option) {
case 1: cout << "enter a name: "; cin >> s; l.add(s); break;
case 2: cout << "enter name to be deleted: "; cin >> s; l.remove(s); break;
case 3: cout << l; break;
//case 4: cout << "can not be done with a singly linked list" << endl;
case 4: l.reversePrint(); break;
case 5: cout << "exiting" << endl; go = false; break;
}
}
system("pause");
}
void linkedList::remove(string s) {
bool found = false;
node *curr = getTop(), *prev = NULL;
while (curr != NULL) {
// match found, delete
if (curr->name == s) {
found = true;
// found at top
if (prev == NULL) {
node *temp = getTop();
setTop(curr->next);
delete(temp);
// found in list - not top
}
else {
prev->next = curr->next;
delete(curr);
}
}
// not found, advance pointers
if (!found) {
prev = curr;
curr = curr->next;
}
// found, exit loop
else curr = NULL;
}
if (found)cout << "Deleted " << s << endl;
else cout << s << " Not Found " << endl;
}
void linkedList::add(string s) {
node *n = new node();
n->name = s;
n->next = NULL;
n->prev = NULL;
// take care of empty list case
if (empty()) {
top = n;
end = n;
// take care of node belongs at beginning case
}
else if (getTop()->name > s) {
n->next = getTop();
n->prev = NULL;
setTop(n);
node *temp;
temp = n->next;
temp->prev = n;
// take care of inorder and end insert
}
else {
// insert in order case
node *curr = getTop(), *prev = curr;
while (curr != NULL) {
if (curr->name > s)break;
prev = curr;
curr = curr->next;
}
if (curr != NULL) { // search found insert point
n->next = curr;
cout << n->name << " " << n << " prev " << prev << " " << prev->name << endl;
n->prev = prev;
prev->next = n;
cout << "n->prev is: " << n->prev << " " << n->prev->name << endl;
cout << "n->next is: " << n->next << " " << n->next->name << endl;
}
// take care of end of list insertion
else if (curr == NULL) {// search did not find insert point
prev->next = n;
n->prev = prev;
cout << "n->prev is: " << n->prev << " " << n->prev->name << endl;
setEnd(n);
}
}
}
ostream& operator << (ostream& os, const linkedList& ll) {
//linkedList x = ll; // put this in and the code blows up - why?
node *n = ll.top;
if (n == NULL)cout << "List is empty." << endl;
else
while (n != NULL) {
os << n->name << endl;
os << n << endl;
if (n->next != NULL) {
os << "next is " << n->next << endl;
}
n = n->next;
}
return os;
}
void linkedList::reversePrint() {
node *n = end;
if (n == NULL)cout << "List is empty." << endl;
else
while (n != NULL) {
//cout << n->name << endl;
cout << "memory address of " << n->name << " is " << n << endl;
if (n->prev != NULL) {
cout << "prev is " << n->prev << endl;
}
n = n->prev;
}
return;
}
// return memory to heap
linkedList::~linkedList() {
cout << "~linkedList called." << endl;
node *curr = getTop(), *del;
while (curr != NULL) {
del = curr;
curr = curr->next;
delete(del);
}
}
int linkedList::menu() {
int choice = 0;
while (choice < 1 || choice > 5) {
cout << "\nEnter your choice" << endl;
cout << " 1. Add a name." << endl;
cout << " 2. Delete a name." << endl;
cout << " 3. Show list." << endl;
cout << " 4. Show reverse list. " << endl;
cout << " 5. EXIT " << endl;
cin >> choice;
}
return choice;
}
You are not setting the prev of the current in insertion into middle, just do:
n->next = curr;
curr->prev = n; // <-- this
I have many functions in my CustomerList.cpp file, the only one of which that doesn't work is shown below (and the break point is marked with a comment). NOTE: Store class is correct, and m_pHead is a CustomerList private variable (but that shouldn't matter).
bool CustomerList::removeStore(int ID)
{
Store *back, *temp;
if(m_pHead = NULL)
{
cout << "\nError! Store " << ID << " not found in the List!\n";
system("pause");
return false; // nothing to delete
}
// Search for the item to delete
back = NULL;
temp = m_pHead;
while((temp != NULL) && (temp->getStoreID() != ID))
{
back = temp;
temp = temp->m_pNext;
}
if(back == NULL) // Delete the first item in the list
{
m_pHead = temp->m_pNext; // THE FUNCTION BREAKS HERE
delete temp;
cout << "\nSuccess! Store " << ID << " added to List!\n";
system("pause");
return true;
}
else if(temp != NULL) // Delete from middle or end of list
{
back->m_pNext = temp->m_pNext;
delete temp;
cout << "\nSuccess! Store " << ID << " added to List!\n";
system("pause");
return true;
}
else
{
cout << "\nError! Store " << ID << " not found in the List!\n";
system("pause");
return false; // Didn't find the item to delete
}
}
Every time I make a call to this function, it breaks, even if the ID of the Store is not on the list (it shouldn't make it that far in the function).
Here is an example of a call:
// Creating a new Customer List
CustomerList *newList = new CustomerList();
newList->removeStore(3);
What in the world am I doing wrong?
There are some logic errors in your code. Most notably, this line;
if(m_pHead = NULL)
Is assigning NULL to m_pHead before then comparing it. Thus, temp is NULL, and back remains NULL, which is why your code reaches the spot you commented and crashes.
You need to use the == comparison operator, not the = assignment operator (your compiler should have warned you about that):
if(m_pHead == NULL)
Or safer:
if(!m_pHead)
Now, with that said, you can simplify the rest of the code to the following:
bool CustomerList::removeStore(int ID)
{
Store *temp, *previous;
// Search for the item to delete
previous = NULL;
temp = m_pHead;
while (temp != NULL)
{
if (temp->getStoreID() == ID)
{
if (m_pHead == temp)
{
// Deleting the first item in the list
m_pHead = temp->m_pNext;
}
if (previous != NULL)
{
// Deleting from middle or end of list
previous->m_pNext = temp->m_pNext;
}
delete temp;
cout << "\nSuccess! Store " << ID << " removed from List!\n";
system("pause");
return true;
}
previous = temp;
temp = temp->m_pNext;
}
cout << "\nError! Store " << ID << " not found in the List!\n";
system("pause");
return false; // nothing to delete
}
Or, if you use a standard C++ container, such as std::list, instead of making your own manual linked-list, you can do this instead:
struct isStoreID
{
int m_id;
isStoreID(int id) : m_id(id) {}
bool operator()(const Store &store) { return (store.getStoreID() == m_id); }
};
bool CustomerList::removeStore(int ID)
{
// Search for the item to delete
// where m_list is a std::list<Store>...
std::list<Store>::iterator iter = std::find_if(m_list.begin(), m_list.end(), isStoreID(ID));
bool bWasFound = (iter != m_list.end());
if (bWasFound)
{
m_list.erase(iter);
cout << "\nSuccess! Store " << ID << " removed from List!\n";
}
else
cout << "\nError! Store " << ID << " not found in the List!\n";
system("pause");
return bWasFound;
}
Having a problem where 2 pointers are passed to a method and right before the method returns I confirm with an if statement that the first is NULL, then the method returns and control goes back to main, I check this pointer again and it != NULL.
This happens in a while loop as I'm trying to iterate through a linked list so it ends up being an infinite loop (so I made the cin >> pause to check outputs before it goes crazy).
Inside a switch on a menu input in main I have:
case 'D':
{
cout.setf(ios::left);
cout << setw(20) << "Last Name" << setw(15) << "First Name"
<< setw(10) << "Priority" << setw(10) << "Arrival Time" << endl;
NodeType<PatientType> *printer;
PatientType *patientToPrint = new PatientType();
ER.startIterate(printer, patientToPrint);
while (printer != NULL) {
PatientType::printPatient(*patientToPrint);
ER.iterate(printer, patientToPrint);
if (printer != NULL) {
cout << "printer != NULL" << endl;
} else {
cout << "printer == NULL" << endl;
}
cout << "PAST ITERATE" << endl;
int pause;
cin >> pause;
}
cout << "OUT OF LOOP";
delete printer;
delete patientToPrint;
break;
}
Where NodeType is a template class (so is LinkedListType, which is ER's type)
The startIterate function being called (in LinkedListType file) is:
template<class ItemType>
void LinkedListType<ItemType>::startIterate(NodeType<ItemType> *item, ItemType *itemToPrint) {
if (head != NULL) {
item = head;
*itemToPrint = head->data;
} else {
item = NULL;
itemToPrint = NULL;
}
}
Where head is the head of the linked list (a private pointer to a NodeType)
Then the iterate function (in LinkedListType file also) is:
template<class ItemType>
void LinkedListType<ItemType>::iterate(NodeType<ItemType> *item, ItemType *itemToPrint) {
NodeType<ItemType> *peek = item->next;
if (item->next == NULL) {
std::cout << "item->next == NULL" << std::endl;
}
if (peek != NULL) {
std::cout << "peek != NULL" << std::endl;
item = item->next;
*itemToPrint = item->data;
} else {
std::cout << "peek == NULL" << std::endl;
item = NULL;
itemToPrint = NULL;
if (item == NULL) {
std::cout << "item == NULL" << std::endl;
}
}
}
After you add a couple nodes to the list and input 'D' (print list) the output works at first, printing out the head node's information, and then reads:
item->next == NULL
peek == NULL
item == NULL
printer != NULL
PAST ITERATE
Which doesn't seem to make sense, "printer" in main is the same as "item" in iterate, the output shows that upon leaving iterate it is NULL, and when arriving in main immediately after, it is not NULL.
After inputting an int for the pause variable, it keeps looping through continuously. What's more is it keeps printing out the head node's information each time too, which I also set to NULL at the end of iterate!
void LinkedListType<ItemType>::iterate(NodeType<ItemType> *& item, ItemType *itemToPrint)
See here:
Reason to Pass a Pointer by Reference in C++?
I'm currently implementing a linked list (in my time off!) and am finding that I have functions with structures like this:
void traverseList(node *head){
if(head != 0){
while(head->next !=0){
cout << head->data << endl;
head = head->next;
}
//one extra for the node at the end
cout << head->data << endl;
}
}
I was wondering in anyone knew of a way to eliminate the 'one extra' calls?
Your function can be greatly simplified to:
void traverseList(node *head)
{
for(node * iterator = head; iterator; iterator = iterator->next)
{
cout << iterator->data << endl;
}
}
Change this:
if(iterator != 0){
while(iterator->next !=0){
cout << iterator->data << endl;
iterator = iterator->next;
}
//one extra for the node at the end
cout << iterator->data << endl;
}
to this:
while(iterator != 0) {
cout << iterator->data << endl;
iterator = iterator->next;
}