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;
}
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";
}
}
}
OK so I have a print function for my binary tree program that prints everything in Breadth-First. When I call it, it prints in the order that I would expect it to, however it also deletes all but ones of the nodes and leaves me with an empty tree.
void BST::breadth(Node *& cur_root)
{
if (cur_root != NULL) {
cout << cur_root->m_value;
if (cur_root->m_left != NULL) {
myqueue.push(cur_root->m_left);
}
if (cur_root->m_right != NULL) {
myqueue.push(cur_root->m_right);
}
if (!myqueue.empty()) {
cout << ", ";
cur_root = myqueue.front();
myqueue.pop();
breadth(cur_root);
} else {
cout << "}" << endl;
}
}
}
I assumed that popping the node off of myqueue might have been the problem, yet I don't have this problem when I use my normal print function (In-Order Traversal).
void BST::print(Node *& cur_root)
{
if (cur_root != NULL) {
print(cur_root->m_left);
myqueue.push(cur_root);
print(cur_root->m_right);
}
int sizecompare = myqueue.size();
if (size() == sizecompare) {
while (!myqueue.empty()) {
cout << myqueue.front()->m_value;
myqueue.pop();
if (!myqueue.empty()) {
cout << ", ";
}
}
cout << "}" << endl;
}
}
They both use the same queue of nodes, so I don't understand why they would behave differently when popped. So is the pop function the culprit? If so, why does it only happen on one function? Is there a way I can work around it so my nodes aren't destroyed?
Because you are passing cur_root by reference instead of by value. When your breadth function returns, your cur_root is pointing to something else (the end of the tree).
You can also avoid the recursion:
void BST::breadth(Node* root)
{
std::queue<Node*> myqueue;
myqueue.push_back(root);
bool first = true;
cout << "{";
while (myqueue.empty() == false) {
cout << (first ? "" : ",");
first = false;
Node* current = myqueue.front();
myqueue.pop();
cout << current->m_value;
if (current->left) {
myqueue.push(current->left);
}
if (current->right) {
myqueue.push(current->right);
}
}
cout << "}" << endl;
}
void BST::breadth(Node *& cur_root)
Takes in a reference to a pointer.
cur_root = myqueue.front();
Changes it to be one of the child nodes. You just overwrote it.
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
So I have a project for my C++ class and we are asked to create a library program using Stacks and Doubly Linked Lists. Now we cannot use the stack header file so everything from push, pop, display, etc. has to created by us.
I have the push function working, but the display function I cannot seem to get it to display more than just the lastNode stuct. When it tries to access previousNode, it crashes. Any ideas on what I'm doing wrong?
Also I can not get the pop function to work either. The program crashes as well when it runs.
void pushBook(BookStack *bkStack, BookNode *bkNode)
{
if(isEmpty(bkStack))
{
bkStack->lastNode = bkNode;
bkStack->lastNode->previousNode = NULL;
}
else
{
bkStack->lastNode->previousNode = bkStack->lastNode;
bkStack->lastNode = bkNode;
}
}
BookNode *popBook(BookStack *bkStack)
{
BookNode *temp = new BookNode;
if(isEmpty(bkStack))
{
temp = bkStack->lastNode;
return temp;
}
else if(bkStack->lastNode->previousNode == NULL)
{
temp = bkStack->lastNode;
bkStack->lastNode = NULL;
return temp;
}else
{
temp = bkStack->lastNode->previousNode;
bkStack->lastNode->previousNode = NULL;
bkStack->lastNode = temp;
return temp;
}
}
void displayStackElements(BookStack *bkStack)
{
BookNode *nodePtr = new BookNode;
nodePtr = bkStack->lastNode;
if(isEmpty(bkStack))
{
cout << "Book stack is empty." << endl;
}
else
{
while(nodePtr != NULL)
{
cout << "\nBook Name: " << nodePtr->bk.name << endl;
cout << "Author Name: " << nodePtr->bk.authorName << endl;
cout << "Page Numbers: " << nodePtr->bk.pagesNumber << endl;
cout << "ISBN: " << nodePtr->bk.isbn << endl;
cout << endl;
nodePtr = bkStack->lastNode->previousNode;
}
}
}
bool isEmpty(BookStack *bkStack)
{
bool status;
if(bkStack->lastNode == NULL)
status = true;
else
status = false;
return status;
}
void addBook(BookStack *bkStack)
{
BookNode *bkNode = new BookNode;
cout << "\nEnter the book name: ";
getline(cin, bkNode->bk.name);
cout << "Enter the Author's Name: ";
getline(cin, bkNode->bk.authorName);
cout << "Enter the ISBN: ";
cin >> bkNode->bk.isbn;
cout << "Enter the page numbers: ";
cin >> bkNode->bk.pagesNumber;
pushBook(bkStack, bkNode);
}
void removeBook(BookStack *bkStack)
{
BookNode *removedNode = new BookNode;
removedNode = popBook(bkStack);
if(removedNode == NULL)
{
cout << "\nNo books to remove." << endl;
}else
{
cout << endl << removedNode->bk.name << " was removed." << endl;
}
}
(edit) Sorry about that here's the structs from the main header file
struct Book
{
int isbn;
string name;
string authorName;
int pagesNumber;
};
struct BookNode
{
Book bk;
BookNode *previousNode;
};
struct BookStack
{
BookNode *lastNode = NULL;
};
I haven't done c++ in a while so if any of the statement below are wrong, tell me so !
Here what I see :
In displayStackElements:
nodePtr = bkStack->lastNode->previousNode; should be nodePtr = nodePtr->previousNode; otherwise, you will always display the previousnode of lastnode of bkStack in an infinite loop !
I don't know why you do this everywhere:
BookNode *nodePtr = new BookNode;
nodePtr = bkStack->lastNode;
You don't need a new BookNode if you are assigning it right after it ! You are creating a new BookNode in memory and then overwrite the pointer. This is a memory leak. You can simply do this:
BookNode *nodePtr = bkStack->lastNode;
In your pop function, the last else code should be this. You want to pop out the lastnode, not the previous node of the current last node.
temp = bkStack->lastNode->previousNode;
BookNode *lastNode = bkStack->lastNode
bkStack->lastNode->previousNode = NULL;
bkStack->lastNode = temp;
return lastNode;
In your push function, you are setting the previousNode of last node but after that, you were overwriting the lastNode with the node passed in parameter. Your list became broken because the lastNode->previousNode will always be emtpy. The else statement should be this.
bkNode->previousNode = bkStack->lastNode;
bkStack->lastNode = bkNode;
As you don't show the BookNode class definition or its constructor, I can only assume that you forget to clear the nodes previousNode pointer, which means that after you add the second second node then bkStack->lastNode->previousNode will be an uninitialized pointer.
Dereferencing uninitialized pointers leads to undefined behavior.
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++?