void deleteBasedOnID(student* head,student* tail,int stu_ID)
{
if (head == NULL)
{
std::cout << "nothing to be deleted";
}
else if (stu_ID == head->stu_ID)
{
//delete from the beginning
temp = head->next;
if (temp == NULL)
{
tail = NULL;
}
else
{
temp->prev = NULL;
}
std::cout << "Deleted ID: " << head->stu_ID << std::endl;
delete head;
head = temp;
}
else
{
//start from second
temp = head;
previous = NULL;
while (stu_ID != temp->stu_ID)
{
previous = temp;
temp = temp->next;
if (temp == NULL)
{
std::cout << "no such ID!" << std::endl;
return;
}
}
previous->next = temp->next;
if (temp->next == NULL)
{
tail = previous;
}
else
{
temp->next->prev = previous;
}
std::cout << "Deleted ID: " << temp->stu_ID << std::endl;
delete temp;
}
}
I have a student struct and global pointers head and tail, I put the said head and tail into deleteBasedOnID head and tail arguments
it works fine for if(head == NULL) or the else block but however whenever I try to delete from the beginning, it works fine internally but after I tried to display the list, error occurred.
This is my display function body
void display()
{
temp = head;
while (temp != NULL)
{
std::cout << "Student ID: " << temp->stu_ID << std::endl;
temp = temp->next;
}
}
main function
int main()
{
head = NULL;
tail = NULL;
temp = NULL;
int id;
std::cout << std::endl;
std::cout << "Enter the id you want to delete: ";
std::cin >> id;
deleteBasedOnID(head, tail, id);
std::cout << "New sorted list" << std::endl;
display();
return 0;
}
In your deleteBasedOnId-function, you change the value for the parameter head, which is a copy of the pointer to head you made in main. The original pointer in main keeps its value, which now points to deleted memory, hence the segfault. You can take a reference to the pointer to head as parameter to solve this problem:
void deleteBasedOnID(student*& head,student*& tail,int stu_ID)
Related
I am trying to reverse a liked list in c++ but unfortunately I am unable to do that. Here is the entire program I am working on. I don't know where the problem is. The problem I think is either
reverse()
or
displayList()
void reverse()
{
struct node *curr = head;
struct node *next = NULL;
struct node *prev = NULL;
while (curr != NULL)
{
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
head = prev;
}
void displayList()
{
while (head != NULL)
{
cout << head->data << " ";
head = head->next;
}
cout << endl;
}
int main(){
createNode(100);
createNode(310);
createNode(150);
createNode(300);
createNode(500);
cout << "Original List" << endl;
displayList();
cout << endl << "Reversed List" << endl;
reverse();
displayList();
return 0;
}
When I comment displayList() when I first called it, it worked. Basically the function runs only one time.
Assuming displayList to be a member function of some List type because there is no local variable head anywhere: You destroy your list (leaking all data) when iterating over it in displayList. Here are some fixes.
void displayList() const
{
node* curr = head;
while (curr != nullptr)
{
std::cout << curr->data << ' ';
curr = curr->next;
}
std::cout << '\n';
}
If you get into the habit of making functions const that are not supposed to change the object, your compiler would have spotted this for you.
*Create a simple linked list program to create a class list containing
class node {
void *info;
node *next;
public:
node (void *v) {info = v; next = 0; }
void put_next (node *n) {next = n;}
node *get_next ( ) {return next;}
void *get_info ( ) {return info;}
};
Be able to initially fill the list. Provide functions to insert/append nodes and remove nodes from the linked list. Be able to display the contents of the list.
Write a little driver program with at least 5 values passed in (so that 5 nodes are created) as you insert/append, delete and display data, showing the programs operation.
Output: While displaying the data, make sure you use an informational label–using the terms “insert”, “append”, “remove” and any other term which displays the action. All data that is displayed must be displayed in a way in which the mentor can easily read and understand.*
My code runs but it throws Exception thrown: write access violation. this was nullptr. on Line 20 when I debug it. In the output it also stops at Delete 04 of my list and outputs no further data after line 156. I am not sure how to fix this. I tried to force it to output the new list with another cout statement but that did not work. Any assistance would be appreciated. Entire code below.
#include <iostream>
#include <iomanip>
using namespace std;
class Node
{
void* info;
Node* next;
public:
Node(void* v) { info = v; next = 0; }
void put_next(Node* n)
{
next = n;
}
Node* get_next()
{
return next;
}
void* get_info()
{
return info;
}
};
class List {
Node* head;
public:
List() { head = NULL; };
void PRINT();
void APPEND(void* info);
void DELETE(void* info);
};
void List::PRINT() {
Node* temp = head;
if (temp == NULL)
{
cout << "Enter Values" << endl;
return;
}
if (temp->get_next() == NULL)
{
cout << *(int*)temp->get_info();
cout << " => ";
cout << "Invalid" << endl;
}
else
{
while (temp != NULL)
{
cout << *(int*)temp->get_info();
cout << " --> ";
temp = temp->get_next();
}
cout << "Invalid" << endl;
}
}
void List::APPEND(void* info) {
Node* newNode = new Node(info);
newNode->put_next(NULL);
Node* temp = head;
if (temp != NULL)
{
while (temp->get_next() != NULL)
{
temp = temp->get_next();
}
temp->put_next(newNode);
}
else
{
head = newNode;
}
}
void List::DELETE(void* info) {
Node* temp = head;
if (temp == NULL)
{
cout << "Enter Values" << endl;
return;
}
if (temp->get_next() == NULL)
{
if ((int*)(temp->get_info()) == info)
{
delete temp;
head = NULL;
}
}
else
{
Node* previous = NULL;
while (temp != NULL)
{
if ((int*)(temp->get_info()) == info) break;
previous = temp;
temp = temp->get_next();
}
previous->put_next(temp->get_next());
delete temp;
}
}
int main()
{
List list;
int a = 04;
int b = 11;
int c = 12;
int d = 15;
int e = 29;
int* Node1 = &a;
int* Node2 = &b;
int* Node3 = &c;
int* Node4 = &d;
int* Node5 = &e;
cout << "Append: 04" << endl;
list.APPEND(Node1);
cout << "Append: 11" << endl;
list.APPEND(Node2);
cout << "Append: 12" << endl;
list.APPEND(Node3);
cout << "Append: 15" << endl;
list.APPEND(Node4);
cout << "Append: 29" << endl;
list.APPEND(Node5);
cout << endl << "Print List" << endl;
list.PRINT();
cout << endl << "Delete 04" << endl;
list.DELETE(Node1);
list.PRINT();
cout << "Start New List" << endl;
cout << endl << "Delete 12" << endl;
list.DELETE(Node3);
list.PRINT();
return 0;
}
SOLUTION:
//Node.h
#pragma once
class Node
{
void* info;
Node* next;
public:
Node(void* v) { info = v; next = 0; }
void put_next(Node* n)
{
next = n;
}
Node* get_next()
{
return next;
}
void* get_info()
{
return info;
}
};
//List.h
#pragma once
#include "Node.h"
#include <iomanip>
class List {
Node* head;
public:
List() { head = NULL; };
void PRINT();
void APPEND(void* info);
void DELETE(void* info);
};
//List.cpp
#include <iostream>
#include "List.h"
using namespace std;
void List::PRINT() {
Node* temp = head;
if (temp == NULL)
{
cout << "Enter Values" << endl;
return;
}
if (temp->get_next() == NULL)
{
cout << *(int*)temp->get_info();
cout << " => ";
cout << "Invalid" << endl;
}
else
{
while (temp != NULL)
{
cout << *(int*)temp->get_info();
cout << " --> ";
temp = temp->get_next();
}
cout << "Invalid" << endl;
}
}
void List::APPEND(void* info) {
Node* newNode = new Node(info);
newNode->put_next(NULL);
Node* temp = head;
if (temp != NULL)
{
while (temp->get_next() != NULL)
{
temp = temp->get_next();
}
temp->put_next(newNode);
}
else
{
head = newNode;
}
}
void List::DELETE(void* info) {
Node* temp = head;
if (temp == NULL)
{
cout << "Enter Values" << endl;
return;
}
if (temp->get_next() == NULL)
{
if ((int*)(temp->get_info()) == info)
{
delete temp;
head = NULL;
}
}
else
{
Node* previous = NULL;
while (temp != NULL)
{
if ((int*)(temp->get_info()) == info) {
// if node is head then changing the head
if (temp == head)
head = temp->get_next();
break;
}
previous = temp;
temp = temp->get_next();
}
// skip this operation if node is head
if (temp->get_next() != head)
previous->put_next(temp->get_next());
delete temp;
}
}
//Main.cpp
#include <iostream>
#include "List.h"
using namespace std;
int main()
{
List list;
int a = 04;
int b = 11;
int c = 12;
int d = 15;
int e = 29;
int* Node1 = &a;
int* Node2 = &b;
int* Node3 = &c;
int* Node4 = &d;
int* Node5 = &e;
cout << "Append: 04" << endl;
list.APPEND(Node1);
cout << "Append: 11" << endl;
list.APPEND(Node2);
cout << "Append: 12" << endl;
list.APPEND(Node3);
cout << "Append: 15" << endl;
list.APPEND(Node4);
cout << "Append: 29" << endl;
list.APPEND(Node5);
cout << endl << "Print List" << endl;
list.PRINT();
cout << endl << "Delete 04" << endl;
list.DELETE(Node1);
list.PRINT();
cout << "Start New List" << endl;
cout << endl << "Delete 12" << endl;
list.DELETE(Node3);
list.PRINT();
return 0;
}
So whenever you are deleting first node, you missed to set the head to the next node of head.
Commented at the parts which are modified in the else statement of DELETE function
Code:
else
{
Node* previous = NULL;
while (temp != NULL)
{
if ((int*)(temp->get_info()) == info){
// if node is head then changing the head
if (temp == head)
head = temp->get_next();
break;
}
previous = temp;
temp = temp->get_next();
}
// skip this operation if node is head
if (temp->get_next() != head)
previous->put_next(temp->get_next());
delete temp;
}
I am new with linked lists and I am getting this error when trying to remove one of the nodes of a linked list.
Exception thrown: Exception thrown: read access violation.
std::_String_alloc<std::_String_base_types<char,std::allocator<char> > >::_Mysize(...) returned 0xDDDDDDF1. occurred
Code:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
struct node
{
string song, artist;
node* next;
};
node* add(node *head)
{
string song, artist;
cout << "Enter song name:" << endl;
getline(cin, song);
cout << "Enter artist name:" << endl;
getline(cin, artist);
node *new_ptr = new node;
new_ptr->song = song;
new_ptr->artist = artist;
if (head == nullptr)
{
head = new_ptr;
head->next = nullptr;
}
else
{
node *ptr = head;
while (ptr->next != nullptr)
{
ptr = ptr->next;
}
ptr->next = new_ptr;
ptr->next->next = nullptr;
}
cout << "Song added." << endl;
return head;
}
node* remove(node *head)
{
if (head == nullptr)
{
cout << "There are no songs." << endl;
return head;
}
string song_to_remove;
bool found = false;
cout << "Enter song name to remove:" << endl;
getline(cin, song_to_remove);
if (head->song.compare(song_to_remove) == 0)
{
found = true;
node *temp = head;
head = head->next;
delete temp;
}
else if(head->next != nullptr)
{
node *prev_ptr = head;
node *ptr = head->next;
while (ptr != nullptr)
{
if (ptr->song.compare(song_to_remove) == 0)
{
found = true;
node *temp = ptr;
prev_ptr->next = ptr->next;
delete temp;
}
ptr = ptr->next;
prev_ptr = prev_ptr->next;
}
}
if (!found)
{
cout << "Song not found." << endl;
}
else
{
cout << "Song removed." << endl;
}
return head;
}
void print(node *head)
{
node* ptr = head;
if (ptr == nullptr)
{
cout << "There are no songs added yet." << endl;
}
else
{
while (ptr != nullptr)
{
cout << ptr->song << " by " << ptr->artist << endl;
ptr = ptr->next;
}
}
}
int main()
{
node *head = nullptr;
int option;
while (1)
{
cout << "Choose an option: Add a song (1), remove a song (2), or list all the songs (3)." << endl;
cin >> option;
cin.ignore();
if (!(option == 1 || option == 2 || option == 3))
{
cout << "Must pick either 1, 2, or 3." << endl;
continue;
}
if (option == 1)
{
head = add(head);
}
else if (option == 2)
{
head = remove(head);
}
else if (option == 3)
{
print(head);
}
}
return 0;
}
I have everything working besides the remove() function, and it only errors when I have more than 1 item in the linked list and when I try to remove a node besides the first one.
I got it. I didn't have a break statement after deleting ptr and then was trying to assign something to ptr. I was trying to make it work so that if you had multiple songs with the same name it would delete all of them, but the program doesn't need to be that specific.
node* remove(node *head)
{
if (head == nullptr)
{
cout << "There are no songs." << endl;
return head;
}
string song_to_remove;
bool found = false;
cout << "Enter song name to remove:" << endl;
getline(cin, song_to_remove);
if (head->song == song_to_remove)
{
found = true;
node *temp = head;
head = head->next;
delete temp;
}
else if(head->next != nullptr)
{
node *prev_ptr = head;
node *ptr = head->next;
while (ptr != nullptr)
{
if (ptr->song == song_to_remove)
{
found = true;
prev_ptr->next = ptr->next;
delete ptr;
break;
}
ptr = ptr->next;
prev_ptr = prev_ptr->next;
}
}
if (!found)
{
cout << "Song not found." << endl;
}
else
{
cout << "Song removed." << endl;
}
return head;
}
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.
I'm creating a database for school records for a project. I have a Student, Faculty, and Administrator class that all inherit things from a Person class. When I add the different objects to a Node, the information is stored in that Node (I see it via the debugger), however when I go to print a Node, I get
00266A88
instead of
Full Name: Reed
M Number: 999
Email:
and so on.
I'm just not sure what is causing the problem. Here is my method to print a node from the list:
template <typename T>
void TemplatedList<T>::printSpecific(int m_Number)
{
Node * Current = Head;
//If there is nothing in the list but the dummy head node, then return because there's nothing to print
if(Head->next == NULL)
{
cout << "Cannot print (M" << m_Number << "), NOT found!" << endl;
return;
}
else
Current = Current->next;
// While Current->next isn't equal to NULL, go through the list and see if the M-Numbers match. If they do, print the student and return
while(Current->next != NULL)
{
if(m_Number == Current->data->getM_Number())
{
cout << Current->data;
return;
}
else
{
Current = Current->next;
}
}
if(Current->next == NULL)
{
if(m_Number == Current->data->getM_Number())
{
cout << Current->data;
return;
}
else
{
cout << "Cannot print (M" <<m_Number << "), NOT found!" << endl;
return;
}
}
}
Here is the function to add one of the of the objects to the list:
template<typename T>
void TemplatedList<T>::addTemplatedList(T newAddition)
{
//Points to current node we're using
Node* Current = Head;
//Points to the node previous in the list to the current
Node* Previous = Head;
//Creates a new Node
Node* newNode = new Node;
//Assigns new Student information to new Node
newNode->data = newAddition;
// Check to see if the Head is only thing in the list. If it is, just place the new Node directly after the Head
if (Head->next == NULL)
{
Head->next = newNode;
newNode->next = NULL;
return;
}
else
{
while (Current->next != NULL)
{
if (newAddition->getM_Number() < Current->next->data->getM_Number())
{
newNode->next = Current->next;
Previous->next = newNode;
return;
}
else if (newAddition->getM_Number() == Current->next->data->getM_Number())
{
cout << "Person with M Number " << newAddition->getM_Number() << " not added because they are already in database." << endl;
delete newNode;
return;
}
Current = Current->next;
Previous = Previous->next;
}
if (Current->next == NULL)
{
Current->next = newNode;
newNode->next = NULL;
}
}
}
And finally here is how I'm calling the add function and creating a new object:
if (inputArray[0] == "A")
{
cout << "Adding Administrator: " << endl <<"\tFull Name:\t" << inputArray[1] << endl;
cout << "\tM Number:\t" << inputArray[2] << endl << "\tEmail Addr:\t" << inputArray[3] << endl << "\tTitle:\t " << inputArray[4] << endl;
Administrator *newAdmin = new Administrator;
istringstream stream (inputArray[2]);
int number;
stream >> number;
newAdmin->setAdmin(inputArray, number);
templatedList.addTemplatedList(newAdmin);
}
I would really appreciate and help that I can get because I'm just not sure what's happening or why it's giving me that incorrect output.
It looks like Node::data is a pointer to Administrator in this example. So when you do
cout << Current->data;
it merely outputs the pointer value. Assuming that you have implemented operator<< for the Administrator class, all you need to do is dereference:
cout << *Current->data;