Can't delete node from node list - c++

I have a little problem which occurs after trying to execute function delete_all(). Any idea why Visual Studio is throwing me an error:
Invalid address specified to RtlValidateHeap, instruction __debugbreak() or something similar
Everything works perfect until I want to execute this function.
#include <iostream>
using namespace std;
struct node {
string name = "n1";
node* prev = NULL;
node* next = NULL;
};
node* add(node* first, string name) {
if (first == NULL) {
return NULL;
}
node* nowy = new node;
if (first->next == NULL) {
nowy->prev = first;
first->next = nowy;
}
else {
while (first->next != NULL) {
first = first->next;
}
nowy->prev = first;
first->next = nowy;
}
nowy->name = name;
return nowy;
}
void writeout(node* first) {
if (first == NULL) cout << "first = NULL";
while (first->next != NULL) {
cout << first->name;
cout << "\n";
first = first->next;
}
if (first->next == NULL) {
cout << first->name;
cout << "\n";
}
}
void delete_all(node* first) {
node* temp;
while (first != NULL) {
temp = first->next;
delete first;
first = temp;
}
}
int main()
{
node n1;
add(&n1, "n2");
add(&n1, "n3");
writeout(&n1);
delete_all(&n1);
}

You declared an object in main() with automatic storage duration as the first node of the list:
node n1;
You may not destroy it using the delete operator.
Using your approach of the list implementation, you could define the function delete_all() the following way:
void delete_all(node* first)
{
if ( first != nullptr )
{
while ( first->next != nullptr )
{
node *temp = first->next;
first->next = temp->next;
delete temp;
}
}
}
But, it will be much better if initially in main(), you declared a pointer to a node. In this case, you will need to update the functions.

Your implementation of delete_all() is fine, but you are passing it a pointer to a node instance that was not created with new, so delete'ing that node is undefined behavior. ALL of your node instances should be created dynamically, including the 1st node.
As such, your add() function should be updated to not blindly return without creating a new node instance if first is initially NULL. You should instead update the caller's node* pointer to point at the new node that was created.
Also, writout() has undefined behavior if first is NULL, because you are unconditionally accessing first->next whether first is NULL or not.
With that said, try something more like this instead:
#include <iostream>
using namespace std;
struct node {
string name = "n1";
node* prev = nullptr;
node* next = nullptr;
};
node* add(node* &first, string name) {
if (!first) {
first = new node{name};
return first;
}
else {
node *prev = first;
while (prev->next) {
prev = prev->next;
}
prev->next = new node{name, prev};
return prev->next;
}
}
/* alternatively:
node* add(node* &first, string name) {
node **nowy = &first, *prev = nullptr;
while (*nowy) {
prev = *nowy;
nowy = &(prev->next);
}
*nowy = new node{name, prev};
return *nowy;
}
*/
void writeout(node* first) {
if (!first) {
cout << "first = NULL";
}
else {
do {
cout << first->name;
first = first->next;
if (first) cout << '\n';
}
while (first);
}
}
void delete_all(node* first) {
node* temp;
while (first) {
temp = first->next;
delete first;
first = temp;
}
}
int main()
{
node* n1 = nullptr;
add(n1, "n2");
add(n1, "n3");
writeout(n1);
delete_all(n1);
}
Alternatively:
...
node* add(node* first, string name) {
if (!first) {
return new node{name};
}
else {
while (first->next) {
first = first->next;
}
first->next = new node{name, first};
return first->next;
}
}
/* alternatively
node* add(node* first, string name) {
// same as node** further above ...
}
*/
...
int main()
{
node* n1 = add(nullptr, "n2");
add(n1, "n3");
...
delete_all(n1);
}

Related

Passing by Pointer Issue

I'm trying to implement my own version of a linked list for learning. I have the following code. The reverseList function works correctly and if I print it inside that function it is good.
However, when I leave the function and then call the print method I get the the first value and then nothing (null). I'm guessing when I get out of the function it brings me back to the original first ([99]) element which is now actually the last element. So my print method outputs the element sees null is the next and ends.
Or I was thinking the changes I was making in the function were somehow only in that function's scope even though I passed a pointer, but that doesn't make sense because if that's the case then I should have all the original data still.
struct ListNode
{
int value;
ListNode* next = NULL;
};
void insertRecList(ListNode* list, int value)
{
if(list->next == NULL)
{
ListNode* end = new ListNode;
end->value = value;
list->next = end;
}
else
insertRecList(list->next, value);
}
void printList(ListNode* list)
{
std::cout << list->value << std::endl;
while(list->next != NULL)
{
list = list->next;
std::cout << list->value << std::endl;
}
}
void reverseList(ListNode* list)
{
ListNode* next;
ListNode* prev = NULL;
ListNode* cur = list;
while(cur != NULL)
{
if(cur->next == NULL)
{
cur->next = prev;
break;
}
else
{
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
}
list = cur;
std::cout << cur->value << " list:" << list->value << std::endl;
}
void testLinkedList()
{
srand(time(NULL));
ListNode nodes;
nodes.value = 99;
int val;
for(int i = 0; i < 5; i++)
{
val = rand() % 30 + 1;
insertRecList(&nodes, i);
//insertList(&nodes, val);
}
printList(&nodes);
reverseList(&nodes);
printList(&nodes);
}
int main()
{
testLinkedList();
return 0;
}
Appreciative of any help you guys can give me,
Thanks!
Update:
By passing the ListNode *list to reverseList, you create a copy of your pointer which point to the same address with nodes. Inside the function, you assign list to the updated cur pointer but the copy will be destroyed at the end. list still points to the same address as before passing to reverseList but its next has changed.
I have modified your code a little bit:
#include <cstdlib>
#include <iostream>
struct ListNode
{
int value;
ListNode* next = nullptr;
};
void insertRecList(ListNode* list, int value)
{
if(list->next == nullptr)
{
ListNode* end = new ListNode;
end->value = value;
list->next = end;
}
else
insertRecList(list->next, value);
}
void printList(ListNode* list)
{
std::cout << list->value << std::endl;
while(list->next != nullptr)
{
list = list->next;
std::cout << list->value << std::endl;
}
}
void reverseList(ListNode** list)
{
ListNode* cur = *list;
ListNode* next = cur->next;
ListNode* prev = nullptr;
while(cur != nullptr)
{
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
*list = prev;
}
void cleanNodes(ListNode *list) {
// clean goes here
}
void testLinkedList()
{
srand(time(nullptr));
ListNode *nodes = new ListNode();
nodes->value = 99;
int val;
for(int i = 0; i < 5; i++)
{
val = rand() % 30 + 1;
insertRecList(nodes, i);
//insertList(&nodes, val);
}
printList(nodes);
reverseList(&nodes);
printList(nodes);
cleanNodes(nodes);
}
int main()
{
testLinkedList();
return 0;
}
Try to compile with: -std=gnu++11
You don't change nodes in reverseList you're just changing list you're just changing a pointer on your struct which is a temporary object so physically nodes steel the same and pointed on the same first element which now has next attribute pointing on Null so the result of printList is correct. You need to work with pointers e.g.
#include <iostream>
#include <cstdlib>
struct ListNode
{
int value;
ListNode* next = NULL;
~ListNode(){
if(this->next)
delete this->next;
}
};
void insertRecList(ListNode* list, int value)
{
if(list->next == NULL)
{
ListNode* end = new ListNode;
end->value = value;
list->next = end;
}
else
insertRecList(list->next, value);
}
void printList(ListNode* list)
{
std::cout << list->value << std::endl;
while(list->next != NULL)
{
list = list->next;
std::cout << list->value << std::endl;
}
}
ListNode * reverseList(ListNode* list)
{
ListNode* next;
ListNode* prev = NULL;
ListNode* cur = list;
while(cur != NULL)
{
if(cur->next == NULL)
{
cur->next = prev;
break;
}
else
{
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
}
std::cout << cur->value << " list:" << list->value << std::endl;
return cur;
}
void testLinkedList()
{
srand(time(NULL));
ListNode * nodes = new ListNode;
nodes->value = 99;
int val;
for(int i = 0; i < 5; i++)
{
val = rand() % 30 + 1;
insertRecList(nodes, i);
//insertList(&nodes, val);
}
printList(nodes);
nodes = reverseList(nodes);
printList(nodes);
delete nodes;
}
int main()
{
testLinkedList();
return 0;
}
Also, don't forget to delete object created dynamically
Reversing a linked list is not a fundamental operation. It does not belong among the basis operations of your class. It is easier (and safer) to implement it in terms of your other operations. Roughly:
Create an empty list.
While the first list is not empty, remove a node from the front of the first list and insert it into the front of the second list.
The second list is now the reverse of the original.

simple linked list delete fails

I'm learning C++, I try to implement simple singly linked list but the delete node part fails. I could not comprehend why this basic delete_node part is failing. It seems prev->set_next line in delete_node method does not working correctly. I tried to debug it too but failed to spot the error.
using namespace std; //ignore it for simplicity
class Node {
int data;
Node *next;
public:
Node() {}
void set_data(int a_data)
{
data = a_data;
}
void set_next(Node *a_next)
{
next = a_next;
}
int get_data()
{
return data;
}
Node* get_next()
{
return next;
}
};
class List {
Node *head;
public:
List()
{
head = NULL;
}
void print_list();
void append_node(int data);
void delete_node(int data);
};
void List::print_list()
{
Node *temp = head;
if(temp == NULL)
{
cout << "empty" << endl;
return;
}
if(temp->get_next() == NULL)
{
cout << temp->get_data() << "--->";
cout << "NULL" << endl;
}
else
{
do
{
cout << temp->get_data() << "+++>";
temp = temp->get_next();
} while(temp != NULL);
cout << "NULL" << endl;
}
}
void List::append_node(int data)
{
Node *new_node = new Node();
new_node->set_data(data);
new_node->set_next(NULL);
Node *temp = head;
if(temp != NULL)
{
while(temp->get_next()!=NULL)
{
temp = temp->get_next();
}
temp->set_next(new_node);
}
else
{
head = new_node;
}
}
void List::delete_node(int data)
{
Node *temp = head;
if(temp == NULL)
{
return;
}
else
{
Node *prev = NULL;
do
{
prev = temp;
if(temp->get_data() == data)
{
prev->set_next(temp->get_next());
delete temp;
break;
}
temp = temp->get_next();
} while(temp!=NULL);
}
}
int main()
{
List list;
list.append_node(10);
list.append_node(20);
list.append_node(30);
list.append_node(40);
list.append_node(50);
list.append_node(60);
list.delete_node(30); //
list.print_list();
return 0;
}
valgrind gives me following error.
==22232== Invalid read of size 8
==22232== at 0x400D38: Node::get_next() (20_1.cpp:25)
==22232== by 0x400A5E: List::print_list() (20_1.cpp:62)
==22232== by 0x400C6C: main (20_1.cpp:127)
==22232== Address 0x5abdd28 is 8 bytes inside a block of size 16 free'd
==22232== at 0x4C2F24B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22232== by 0x400BA8: List::delete_node(int) (20
Lets take a closer look at these lines from the List::delete_node function
prev = temp;
if(temp->get_data() == data)
{
prev->set_next(temp->get_next());
delete temp;
break;
}
The first one make prev point to the very same node that temp is pointing to. After this prev == temp is true.
So when you do
prev->set_next(temp->get_next());
it is the same as
temp->set_next(temp->get_next());
That is, you make temp->next point to temp->next which doesn't change it at all. You never unlink the node from the list, but you do delete it. That makes your printing of the list invalid, as you will dereference a deleted node.
As a simple solution, you could do something like this:
if (head->get_data() == data)
{
// Special case: Head node is the one we want to delete
Node* old_head = head;
// Make the head be the second node in the list, if any
head = head->get_next();
// Delete the old head
delete old_head;
}
else
{
// We know it's not the head node of the list, use the "next" to find it
for (Node* node = head; node->get_next() != 0; node = node->get_next())
{
if (node->get_next()->get_data() == data)
{
// It's the "next" node we want to remove
Node* old_next = node->get_next();
// Unlink the node
node->set_next(node->get_next()->get_next());
delete old_next;
break;
}
}
}
The problem is that at the beginning of your do / while loop pointers temp and prev point to the same Node. Hence, you re-point the node, and then delete it right away.
A better approach is to not use prev at all. Get next, see if its data matches the one being deleted. If it does, "bypass" and delete next. Otherwise, move on to the next node until you hit NULL:
void List::delete_node(int data) {
if(head == NULL) {
return;
}
if (head->get_data() == data) {
Node *toDelete = head;
head = head->get_next();
delete toDelete;
return;
}
Node *temp = head;
for ( ; ; ) {
Node *next = temp->get_next();
if (next == null) {
break;
}
if (next->get_data() == data) {
temp->set_next(next->get_next());
delete next;
break;
}
temp = temp->get_next();
}
}
The exact working solution is
void List::delete_node(int data)
{
Node *temp = head;
Node *prev = NULL;
//first check whether its a parent element or not
if(temp && temp->get_data() == data){
head = head->get_next();
delete temp;
}
else{
while (temp){
if (temp->get_data() == data){
if (prev)
prev->set_next(temp->get_next());
delete temp;
return;
}
prev = temp;
temp = temp->get_next();
}
}
}
This even works for deleting head node
I see a number of problems with your code.
Your Node constructors is not initializing any of the Node members.
Your List class is missing a destructor to free any allocated nodes.
Your print_list() and append_node() implementations are a little more verbose than they need to be.
But, most importantly, regarding your particular question, your list's delete_node() method is not managing its prev variable correctly. prev is always pointing at the current node that is being looked at, not at the previous node that was already looked at. So you are not actually updating your links correctly when removing a node. You are also not updating the list's head member if the node being removed is the head node.
Try something more like this instead:
class Node;
class List {
Node *head;
public:
List();
~List();
void print_list();
void append_node(int data);
void delete_node(int data);
};
class Node {
int data;
Node *next;
public:
Node(int a_data = 0, Node *a_next = NULL);
void set_data(int a_data);
void set_next(Node *a_next);
int get_data();
Node* get_next();
friend class List;
};
Node::Node(int a_data, Node *a_next)
: data(a_data), next(a_next)
{
}
void Node::set_data(int a_data)
{
data = a_data;
}
void Node::set_next(Node *a_next)
{
next = a_next;
}
int Node::get_data()
{
return data;
}
Node* Node::get_next()
{
return next;
}
List::List()
: head(NULL)
{
}
List::~List()
{
Node *temp = head;
while (temp)
{
Node *next = temp->get_next();
delete temp;
temp = next;
}
}
void List::print_list()
{
Node *temp = head;
if (!temp)
{
cout << "empty" << endl;
return;
}
do
{
cout << temp->get_data();
temp = temp->get_next();
if (!temp) break;
cout << "+++>";
}
while (true);
cout << "--->NULL" << endl;
}
void List::append_node(int data)
{
Node **temp = &head;
while (*temp) temp = &((*temp)->next);
*temp = new Node(data);
}
void List::delete_node(int data)
{
Node *temp = head;
Node *prev = NULL;
while (temp)
{
if (temp->get_data() == data)
{
if (prev)
prev->set_next(temp->get_next());
if (temp == head)
head = temp->get_next();
delete temp;
return;
}
prev = temp;
temp = temp->get_next();
}
}
int main()
{
List list;
list.append_node(10);
list.append_node(20);
list.append_node(30);
list.append_node(40);
list.append_node(50);
list.append_node(60);
list.delete_node(30); //
list.print_list();
return 0;
}

I am getting a breakpoint and i do not know why

I am trying to implement a priority Queue by using a linked list in c++. However, when I run the program it triggers a breakpoint within "priorityQLinkedList::dequeue()" method. Can someone tell why this is the case and give me suggestions on how to fix it?
Code:
#include <iostream>
#include <cstring>
#include <iomanip>
using namespace std;
struct DAT
{
int id;
char fullname[50];
double savings;
};
struct NODE
{
DAT data;
NODE *N;
NODE *P;
NODE(const int i, const char *f, const double s)
{
data.id = i;
strcpy_s(data.fullname, f);
data.savings = s;
N = NULL;
P = NULL;
}
};
class priorityQLinkedList
{
private:
NODE *front;
NODE *back;
public:
priorityQLinkedList() { front = NULL; back = NULL; }
~priorityQLinkedList() { destroyList(); }
void enqueue(NODE *);
NODE* dequeue();
void destroyList();
};
void priorityQLinkedList::enqueue(NODE *n)
{
if (front == NULL) {
front = n;
back = n;
}
else {
NODE *temp = front;
if (n->data.id > temp->data.id)
{
front->P = n;
n->N = front;
front = n;
}
else
{
//search for the posistion for the new node.
while (n->data.id < temp->data.id)
{
if (temp->N == NULL) {
break;
}
temp = temp->N;
}
//New node id's smallest then all others
if (temp->N == NULL && n->data.id < temp->data.id)
{
back->N = n;
n->P = back;
back = n;
}
//New node id's is in the medium range.
else {
temp->P->N = n;
n->P = temp->P;
n->N = temp;
temp->P = n;
}
}
}
}
NODE* priorityQLinkedList::dequeue()
{
NODE *temp;
//no nodes
if (back == NULL) {
return NULL;
}
//there is only one node
else if (back->P == NULL) {
NODE *temp2 = back;
temp = temp2;
front = NULL;
back = NULL;
delete temp2;
return temp;
}
//there are more than one node
else {
NODE *temp2 = back;
temp = temp2;
back = back->P;
back->N = NULL;
delete temp2;
return temp;
}
}
void priorityQLinkedList::destroyList()
{
while (front != NULL) {
NODE *temp = front;
front = front->N;
delete temp;
}
}
void disp(NODE *m) {
if (m == NULL) {
cout << "\nQueue is Empty!!!" << endl;
}
else {
cout << "\nID No. : " << m->data.id;
cout << "\nFull Name : " << m->data.fullname;
cout << "\nSalary : " << setprecision(15) << m->data.savings << endl;
}
}
int main() {
priorityQLinkedList *Queue = new priorityQLinkedList();
NODE No1(101, "Qasim Imtiaz", 567000.0000);
NODE No2(102, "Hamad Ahmed", 360200.0000);
NODE No3(103, "Fahad Ahmed", 726000.0000);
NODE No4(104, "Usmaan Arif", 689000.0000);
Queue->enqueue(&No4);
Queue->enqueue(&No3);
Queue->enqueue(&No1);
Queue->enqueue(&No2);
disp(Queue->dequeue());
disp(Queue->dequeue());
disp(Queue->dequeue());
disp(Queue->dequeue());
disp(Queue->dequeue());
delete Queue;
return 0;
}
One problem which stands out in your dequeue() method is that you are calling delete on a NODE pointer, and then attempting to return this deleted pointer to the caller. This could cause an error either in dequeue() itself, or certainly in the caller who thinks he is getting back a pointer to an actual live NODE object.
One potential fix would be to create a copy of the NODE being dequeued. You would still remove the target from your list, but the caller would then be returned a valid pointer, which he could free later.
NODE* priorityQLinkedList::dequeue()
{
NODE *temp;
// no nodes
if (back == NULL) {
return NULL;
}
NODE *temp2 = back;
temp = new NODE(temp2->data.id, temp2->data.fullname, temp2->data.savings);
// there is only one node
else if (back->P == NULL) {
front = NULL;
back = NULL;
delete temp2;
return temp;
}
// there are more than one node
else {
back = back->P;
back->N = NULL;
delete temp2;
return temp;
}
}
You're deleting pointers in dequeue that priorityQLinkedList does not own, so you don't know if it is safe to delete them.
In this case, they are not since the node pointers passed to enqueue are addresses of local, stacked based variables and have not been allocated by new. (There's also the already mentioned problem of deleting a pointer then returning it, which is Undefined Behavior.)
The fix for the code as shown is to remove the calls to delete in dequeue. However, if changes are made so that the nodes passed to enqueue are dynamically allocated, you'll need to add something to handle that.
1.First change strcpy_s to strcpy is struct NODE.
2.Instead of Delete(temp2) use temp2--.
//no nodes
if (back == NULL) {
return NULL;
}
//there is only one node
else if (back->P == NULL) {
NODE *temp2 = back;
temp = temp2;
front = NULL;
back = NULL;
temp2--;
return temp;
}
//there are more than one node
else {
NODE *temp2 = back;
temp = temp2;
back = back->P;
back->N = NULL;
temp2--;
return temp;
}
I hope this will resolve the problem.

Adding at the end of a linked list and displaying the first value in the linked list?

Im making a Queue singly linked list for an assignment. My insert method should add the value at the end of the linked list. My first() method should return the value of the first node in the linked list. Here is my attempt at this:
void QueueList::insert(const BinType & item)
{
try
{
Node *before = head;
Node *after = before->next;
if (numberOfNodes == 0)
{
before->next = tail = CreateNode(item, after);
}
else
{
Node *tmp = head;
while (tmp && tmp->next != NULL) tmp = tmp->next;
Node *tmp1 = CreateNode(item, nullptr);
if (tmp == NULL)
head = tmp1;
else
tmp->next = tmp1;
}
numberOfNodes++;
}
catch (const std::exception err)
{
cerr << "QueueList Error: " << err.what() << endl;
}
}
My first Method
BinType QueueList::first() const
{
return head->item;
}
My Driver
QueueList one;
one.insert(2);
cout<<one.first()<<endl;
When I do this the console prints 0. I am not sure why its not returning 2?
EDIT: class code
#include "QueueList.h"
#include <sstream>
#include <string>
#include <iostream>
using namespace std;
namespace DB{
void QueueList::releaseNodes()
{
Node *del = head;
while (head != nullptr) {
head = head->next;
del->next = nullptr;
delete del;
del = head;
}
tail = nullptr;
numberOfNodes = 0;
}
QueueList::Node* QueueList::CreateNode(const BinType & item, Node * const next)
{
if (new Node(item,next) == nullptr)
{
throw bad_alloc();
}
return new Node(item,next);
}
QueueList::QueueList()
{
head = tail = CreateNode(BinType(), nullptr);
numberOfNodes = 0;
}
QueueList::~QueueList()
{
releaseNodes();
}
void QueueList::insert(const BinType & item)
{
try
{
Node *before = head;
Node *after = before->next;
if (numberOfNodes == 0)
{
before = tail = CreateNode(item, nullptr);
}
else
{
Node *tmp = head;
while (tmp && tmp->next) tmp = tmp->next;
Node *tmp1 = CreateNode(item, nullptr);
if (tmp == NULL)
head = tmp1;
else
tmp->next = tmp1;
}
numberOfNodes++;
}
catch (const std::exception err)
{
cerr << "QueueList Error: " << err.what() << endl;
}
}
BinType QueueList::remove()
{
if (numberOfNodes == 0)
{
throw bad_alloc();
}
Node *del;
del = head->next;
head->next = del->next;
numberOfNodes--;
}
BinType QueueList::first() const
{
return head->item;
}
int QueueList::size() const
{
return numberOfNodes;
}
bool QueueList::isEmpty() const
{
if (head == nullptr)
{
return true;
}
}
}
The issue you had was you were creating a local variable,before, that was a pointer to the head of your linked list. When inserting, you then changed what before was pointing to. Keep in mind, this had no affect on what the head of your list was actually pointing to. You simply changed before to point to a new node instead of head.
In your project, make sure you're updating the head and tail properties of your class, not local pointers that may be pointing to head and tail. Also, in your class constructor,you should have head set to NULL instead of an actual node. Otherwise, isEmpty will not resolve to true upon creation of an empty list.
Since this is a class project, probably best to let you debug other problems I may see so good luck!! Sometime it's helpful to use GDB to step through your code to find out when it does something you didn't intend it to do.

C++ Linked List Runtime Error: Unhandled Exception - Writing Location Violation

I am trying to build my own implementation of a linked list in C++. My code is compiling but apparently there is some issue with my pointers referring to invalid memory addresses.
Here is my implementation:
#include <iostream>
#include <string>
using namespace std;
class Node
{
private:
string _car;
Node* nextNode;
public:
void setCar(string car)
{
_car = car;
}
string getCar()
{
return _car;
}
void setNextNode(Node* node)
{
nextNode = node;
}
Node* getNextNode()
{
return nextNode;
}
};
Node* findLast(Node* node)
{
Node* nodeOut = NULL;
while (node->getNextNode() != NULL)
{
nodeOut = node->getNextNode();
}
return nodeOut;
}
string toString(Node* node)
{
string output = "";
while (node->getNextNode() != NULL)
{
output += node->getCar() + " ";
node = node->getNextNode();
}
return output;
}
int main()
{
char xit;
//ser head node to NULL
Node* headNode = NULL;
//create node 1
Node* node1 = new Node();
node1->setCar("Mercedes");
//create node 2
Node* node2 = new Node();
node2->setCar("BMW");
//set node links
headNode->setNextNode(node1);
node1->setNextNode(node1);
node2->setNextNode(node2);
headNode = node1;
Node* lastNode = findLast(headNode);
lastNode->setNextNode(NULL);
cout << toString(headNode) << endl;
//pause console
cin >> xit;
}
You need to relook at your code.
headNode = node1;
This assignment should be done before accesing any member function of the instance headNode.
Intially you have assigned NULL to this pointer.
After creating node1 you are setting to headNode that is invalid instance. This is the cause of crash.
Be ensure with your objective and then try to implement do some rough work on paper , make some diagram that way you would be more clear that what you are exactly trying to achive.
why setNextNode ??? i don't undeerstand what you wanted to achieve. be clear first.
As per my undertanding this code should be implemented like below..
#include <iostream>
#include <string>
using namespace std;
class Node
{
private:
string _car;
Node* nextNode;
public:
void setCar(string car)
{
_car = car;
}
string getCar()
{
return _car;
}
void setNextNode(Node* node)
{
nextNode = node;
}
Node* getNextNode()
{
return nextNode;
}
};
Node* findLast(Node* node)
{
Node* nodeOut = node->getNextNode();
while ( nodeOut->getNextNode()!= NULL)
{
nodeOut = nodeOut->getNextNode();
}
return nodeOut;
}
string toString(Node* node)
{
string output = "";
while (node != NULL)
{
output += node->getCar() + " ";
node = node->getNextNode();
}
return output;
}
int main()
{
char xit;
//ser head node to NULL
Node* headNode = NULL;
//create node 1
Node* node1 = new Node();
node1->setCar("Mercedes");
node1->setNextNode(NULL);//Make null to each next node pointer
headNode = node1; //assign the node1 as headNode
//create node 2
Node* node2 = new Node();
node2->setCar("BMW");
node2->setNextNode(NULL);
//set node links
node1->setNextNode(node2);
Node* lastNode = findLast(headNode);
lastNode->setNextNode(NULL);
cout << toString(headNode) << endl;
//pause console
cin >> xit;
}
Hope it would be useful for the beginner who implement ing the linklist in c++.
Reread this:
node1->setNextNode(node1);
node2->setNextNode(node2);
...and think about what you're doing here.
If you're going to write linked-list code, I'd advise at least looking at the interface for std::list. Right now, you're interface is at such a low level that you'd be at least as well off just manipulating pointers directly.
The cause of your actual error is:
headNode->setNextNode(node1);
headNode is still set to NULL, thus you're dereferencing a NULL pointer. As noted by Jerry, you're also calling having nodes point to themselves, which is not what you want.
It would be cleaner if you took the car as a constructor parameter.
When you allocate a new Node, the pointer nextNode is not initialized, it's just random junk. You will need to explicitly set it to NULL (probably in a constructor for Node).
Also, I assume you know that the standard C++ library has a linked list built in and you're just doing this for learning ;-)
Thanks for all the suggestions, here is my final code after major cleanup:
// LinkedListProject.cpp : main project file.
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace System;
using namespace std;
class Node
{
public:
Node()
:_car(""), _nextNode(NULL)
{
}
void SetCar(string car)
{
_car = car;
}
string GetCar()
{
return _car;
}
void SetNextNode(Node *node)
{
_nextNode = node;
}
Node * GetNextNode()
{
return _nextNode;
}
private:
string _car;
Node *_nextNode;
};
string GetData();
Node * AddNode(Node *firstNode, Node *newNode);
Node * DeleteNode(Node *firstNode, string nodeData);
void PrintNodes(Node *firstNode);
int main(int argc, char *argv[])
{
string command = "";
string data = "";
Node *firstNode = NULL;
do
{
cout << "Enter command: ";
cin >> command;
if(command == "add")
{
data = GetData();
Node *newNode = new Node();
newNode->SetCar(data);
firstNode = AddNode(firstNode, newNode);
}
else if(command == "delete")
{
data = GetData();
firstNode = DeleteNode(firstNode, data);
}
else if(command == "print")
{
PrintNodes(firstNode);
}
} while(command != "stop");
return 0;
}
string GetData()
{
string data = "";
cout << "Enter data: ";
cin >> data;
return data;
}
Node * AddNode(Node *firstNode, Node *newNode)
{
//add new node to front of queue
newNode->SetNextNode(firstNode);
firstNode = newNode;
return firstNode;
}
Node * DeleteNode(Node *firstNode, string nodeData)
{
Node *currentNode = firstNode;
Node *nodeToDelete = NULL;
if (firstNode != NULL)
{
//check first node
if(firstNode->GetCar() == nodeData)
{
nodeToDelete = firstNode;
firstNode = firstNode->GetNextNode();
}
else //check other nodes
{
while (currentNode->GetNextNode() != NULL &&
currentNode->GetNextNode()->GetCar() != nodeData)
{
currentNode = currentNode->GetNextNode();
}
if (currentNode->GetNextNode() != NULL &&
currentNode->GetNextNode()->GetCar() == nodeData)
{
nodeToDelete = currentNode->GetNextNode();
currentNode->SetNextNode(currentNode->GetNextNode()->GetNextNode());
}
}
if(nodeToDelete != NULL)
{
delete nodeToDelete;
}
}
return firstNode;
}
void PrintNodes(Node *firstNode)
{
Node *currentNode = firstNode;
while(currentNode != NULL)
{
cout << currentNode->GetCar() << endl;
currentNode = currentNode->GetNextNode();
}
}