Error while parsing through the linked list - c++

Exception thrown at 0x00A12849 in DLL.exe: 0xC0000005: Access violation reading ocation 0xDDDDDDDD.
The error occurs at the parse function and I have no clue why. I wrote the exact same code as in the book they only wrote the del function and not the parse function. pls tell why this error is occurring in this code and how to avoid such in future. also help to write a proper parse function.
thanks to everyone in advance
#include<iostream>
using namespace std;
struct list
{
int data;
list *next;
list *prev;
};
list* createNode()
{
list *node = new list;
node->next = NULL;
node->prev = NULL;
return node;
}
void insert(list**head,int data,int position)
{
int k = 1;
list *current, *temp, *node = createNode();
current = NULL;
temp = *head;
node->data = data;
if (position==1)
{
node->next = *head;
*head = node;
if (*head)
{
(*head)->prev = node;
}
}
else
{
while (temp->next!= NULL&&k < (position-1))
{
temp = temp->next;
k++;
}
node->next = temp->next;
node->prev = temp->prev;
if (temp->next)
temp->next->prev = node;
temp->next= node;
}
}
void del(list**head, int position)
{
int k = 1;
list *current, *temp;
current = NULL;
temp = *head;
if (position == 1)
{
*head = (*head)->next;
if (*head != NULL)
(*head)->prev = NULL;
delete temp;
return;
}
while (k < position&&temp->next != NULL)
{
temp = temp->next;
k++;
}
current = temp->prev;
current->next = temp->next;
if (temp->next)
temp->next->prev = current;
delete temp;
return;
}
void parse(list * temp)
{
while (temp != NULL)
{
cout << "->" << temp->data;
temp = temp->next;
}
}
void main()
{
struct list *head = NULL;
start:
int choice;
cin >> choice;
switch (choice)
{
case 1: int data, position;
cout << "\ndata:"; cin >> data; cout << "\nposition:";
cin>>position;
insert(&head, data, position);
goto start;
case 2:parse(head);
goto start;
case 3: cout << "\nposition:"; cin >> position;
del(&head, position);
goto start;
default: break;
}
exit(0);
}

These steps are in the wrong sequence and make the node its own prev:
*head = node;
if (*head)
{
(*head)->prev = node;
}
Then you also set prev incorrectly here:
node->prev = temp->prev;
The following code is not necessarily incorrect on its own, but it is a needlessly dangerous use of prev that fails do to the bugs that make prev wrong, but also fails in some cases of bad input (invalid position).
while (k < position&&temp->next != NULL)
{
temp = temp->next;
k++;
}
current = temp->prev;
You said that del function was in the book. Maybe you don't have a choice, but you apparently are using a pretty bad book. That function (and your insert function) are written in a beginner style that is not a good way to learn to program. Beginner problems are appropriate for learning, but some aspects of typical beginner solutions should be avoided from the beginning. One of the most important skills in programming is finding the similarities that let you combine related operations into more general operations. Breaking out special cases (such as first position in those functions) is a natural beginner mistake that you should be unlearning, not copying from a book.
You are already using the extra level of indirection ** that enables combining the cases, so you should take full advantage of that, rather than drop the advantage at the first opportunity:
void insert(list**head,int data,int position)
{
list *p = NULL;
while ( (position--)>0 && *head )
{
p = *head;
head = &( p->next );
}
list *node = createNode();
node->prev = p;
node->next = *head;
node->data = data;
*head = node;
}
Notice how many cases are mixed in so they all share the same code. That style cuts down on undiscovered bugs. Learning linked lists is a tiny corner of learning to program. Learning to combine and generalize operations is learning to program.

Related

Merging two linked lists throws _CrtlsValidHeapPointer(block) in MSVC

I am teaching myself data structures in C++ and my current challenge is to create, and merge, two linked lists. However, Microsoft Visual Studio throws the following error:
Debug Assertion Failed! Program: LinkedList\Debug\LinkedList.exe File: minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp Line: 904 Expression: _CrtlsValidHeapPointer(block)
However, it seems to work fine in Wandbox: Source code in Wandbox Online Compiler Where does it go wrong?
This is the source code:
#include <iostream>
#include <cstdlib>
class Node {
public:
int data;
Node* next;
};
class LinkedList {
public:
LinkedList() {
head = nullptr;
}
~LinkedList() {
Node* temp = head;
while (head) {
head = head->next;
delete temp;
temp = head;
}
};
void addNode(int value);
void display();
void merge(LinkedList& list2);
private:
Node* head;
};
void LinkedList::addNode(int value) {
Node* newnode = new Node();
newnode->data = value;
newnode->next = nullptr;
if (head == nullptr) {
head = newnode;
} else {
Node* temp = head; // head is not NULL
while (temp->next != nullptr) {
temp = temp->next; // go to end of list
}
temp->next = newnode; // linking to newnode
}
}
void LinkedList::display() {
if (head == nullptr) {
std::cout << "List is empty!" << std::endl;
} else {
Node* temp = head;
while (temp != nullptr) {
std::cout << temp->data << " ";
temp = temp->next;
}
std::cout << std::endl;
}
}
void LinkedList::merge(LinkedList& list2) {
Node* node = new Node();
node->next = nullptr;
Node* temp = node;
Node* head1 = head;
Node* head2 = list2.head;
while (head1 != nullptr && head2 != nullptr) {
if (head1->data <= head2->data) {
temp->next = head1;
temp = temp->next;
head1 = head1->next;
} else {
temp->next = head2;
temp = temp->next;
head2 = head2->next;
}
}
while (head1 != nullptr && head2 == nullptr) {
temp->next = head1;
temp = temp->next;
head1 = head1->next;
}
while (head2 != nullptr && head1 == nullptr) {
temp->next = head2;
temp = temp->next;
head2 = head2->next;
}
temp = temp->next;
delete temp;
head = node->next;
}
int main() {
LinkedList list;
list.addNode(1);
list.addNode(2);
std::cout << "Linked List Data: " << list.display() << std::endl;
LinkedList list2;
list2.addNode(3);
list.merge(list2);
list.display();
return 0;
}
That MSVC error indicates that you're doing something bad with memory. In this case it seems you're deleting memory twice. Freeing a pointer twice is Undefined Behavior and compilers/runtimes are not required to diagnose the problem.
Your merge seems to be expecting sorted lists, but addNode does not enforce this. Also, once that merge is done, the nodes of list2 will be contained in both the returned list and the original list2. When the LinkedList destructor runs you will (try to) delete those nodes twice. The Microsoft Compiler in Debug builds can tell you about these problems.
There are also issues with memory leaks (e.g., the node allocated in merge is not freed).
The Expression: _CrtIsValidHeapPointer(block) indicates that memory has corrupted, possibly due to writing past the end of a buffer or writing past the end of a class because the writer assumes the class is larger than was allocated (like when it is expecting a derived class and gets a base class, or object of a different class).
Please open Debug->Windows->Exception Settings, In the Exception Settings window, expand the node for a category of exceptions -> Common Language Runtime Exceptions( meaning .NET exceptions), and select the check box for a specific exception within that category System.AccessViolationException. You could also select an entire category of exceptions if you don't know which exception to choose. And then you could see the initial problem.
For more information about how to manage exceptions, please refer to this document below:
https://learn.microsoft.com/zh-cn/visualstudio/debugger/managing-exceptions-with-the-debugger?view=vs-2019&redirectedfrom=MSDN

Problem with inserting into a doubly linked list in ascending order

i need to make a function to sum 2 piecewise linear functions (both decreasing or increasing) and insert them into a third list in an ascending order based on the x-axis coordinates of each point. So i have created multiple functions, all seem to check out except this one yet i do not know what's the problem. It's not inputting anything at all.
struct coords has double x,y;
dList has : coords pt;
node has : node *head, *tail;
node *prev, *next;
dList insert(dList L, coords point) {
node *temp;
temp = new node;
if (temp == NULL) {
cout << "error";
exit(1);
}
temp->next = NULL;
temp->prev = NULL;
temp->pt = point;
if (L.head == NULL || L.tail == NULL) {
L.head = temp;
L.tail = temp;
return L;
}
if (L.head->pt.x > temp->pt.x) {
temp->next = L.head;
L.head->prev = temp;
L.head = temp;
return L;
}
if (L.tail->pt.x < temp->pt.x) {
temp->prev = L.tail;
L.tail->next = temp;
L.tail = temp;
return L;
}
node *cur;
cur = L.head->next;
while (cur->pt.x < temp->pt.x)
cur = cur->next;
temp->next = cur->next;
temp->prev = cur;
cur->next->prev = temp;
cur->next = temp;
return L;
}
The case in which the node to be inserted is in the middle is the problem. You should be looking one node ahead instead of looking at the current one. Try working it out on paper and you will see how that makes a difference:
node * cur;
// also start at head here
cur=L.head;
while(cur->next->pt.x<temp->pt.x)
cur=cur->next;
temp->next=cur->next;
temp->prev=cur;
cur->next->prev=temp;
cur->next=temp;
You should also consider passing a dList L as a pointer to the function and also returning it as a pointer:
// this way you won't be making a copy of it, you may run into trouble if you don't have your copy constructor implemented
dList* insert(dList* L,coords point)
I hope that this helps you.

How can I change this insert function to work in a linked list using strings?

This is the first question that I'm posting on StackOverflow, so forgive me if it seems kinda choppy.
For my computer science class, we're working with a double linked list for the current assignment. One of the functions required is an insert function.
I actually found an insert function on StackOverflow earlier this week, but it was set up to use structures inside of the main file instead of separate class files like this project is using. I think the function can work, but I'm not sure what alterations I need to make so that it can work with class files instead.
LinkedList.h member data
private:
Node *head, *tail;
mutable Node *it;
int count;
Insert function
bool LinkedList::insert(const string & str) const
{
LinkedList * tempVar;
if (hasMore) {
resetIterator();
}
else {
Node * temp = new Node;
//temp = str;
temp->data = str;
temp->next = it;
temp->prev = nullptr;
it->prev = temp;
it = temp;
}
if (it != nullptr) {
Node * current = it;
Node * previous = nullptr;
Node * tempNode = nullptr;
while (current->next != nullptr) {
tempNode = current->next;
if (current->data > tempNode->data) {
swap(current->data, tempNode->data);
}
else {
previous = current;
current = current->next;
}
}
tempVar->count += 1;
}
return false;
}
I haven't been able to test it yet due to not knowing what alterations are needed, but the function should insert strings that are passed into the argument into the linked list, as well as sort them in a dictionary style. Right now the only error is that temp = str; not working, and I'm not entirely sure what I need to do to get it to work.
Try something more like this:
bool LinkedList::insert(const string & str)
{
Node * current = head;
while ((current) && (current->data < str))
current = current->next;
Node *newNode = new Node;
newNode->data = str;
newNode->next = nullptr;
newNode->prev = nullptr;
if (current)
{
if (current->previous)
{
current->previous->next = newNode;
newNode->previous = current->previous;
}
current->previous = newNode;
newNode->next = current;
if (current == head)
head = newNode;
}
else
{
if (!head)
head = newNode;
if (tail)
{
tail->next = newNode;
newNode->previous = tail;
}
tail = newNode;
}
count += 1;
return true;
}
That being said, you really should be using the standard std::list container instead of implementing a double-linked list manually.

Singly Linked List Infinite Loop

It's been a week since i started learning about linked list and i only managed to learn about singly linked list. So today i implemented the linked list which i learned in c++ and while i tried to run it the code goes into an infinite loop of some random numbers. I tried debugging the code but i coudn't find whats so ever is wrong with the code. The code is below. Help is appreciated.Thanks
#include <iostream>
using namespace std;
struct node{
int data;
node * next;
};
class singly{
private:
node * head,*tail;
public:
singly(){
head=NULL;
tail=NULL;
}
void createNode(int value){
node * temp = new node;
temp->data=value;
temp->next=NULL;
if(head==NULL){
head=temp;
tail=temp;
temp=NULL;
}
else{
tail->next=temp;
tail=temp;
}
}
void display(){
node * temp = new node;
head=temp;
while(temp!=NULL){
cout << temp->data << "\t" << endl;
temp->next=temp;
}
}
void insert_end(int value){
node*newnode = new node;
node*temp = new node;
newnode->data=value;
newnode->next=NULL;
temp=head;
while(temp->next!=NULL){
temp = temp->next;
}
temp->next=newnode;
}
void delete_node(){
node*current = new node;
node*previous = new node;
current = head;
while(current->next!=NULL){
previous=current;
current=current->next;
}
tail=previous;
previous->next=NULL;
delete current;
}
};
int main(){
singly lists;
lists.createNode(32);
lists.createNode(654);
lists.createNode(34);
lists.createNode(234);
cout<<"\n--------------------------------------------------\n";
cout<<"---------------Displaying All nodes---------------";
cout<<"\n--------------------------------------------------\n";
lists.display();
cout<<"\n--------------------------------------------------\n";
cout<<"-----------------Inserting At End-----------------";
cout<<"\n--------------------------------------------------\n";
lists.createNode(55);
lists.display();
cout<<"\n--------------------------------------------------\n";
cout<<"-----------------Deleing At End-------------------";
cout<<"\n--------------------------------------------------\n";
lists.delete_node();
lists.display();
}
The member function display does not make sense.
It overwtites the data member head with uninitialized newly created temp.
node * temp = new node;
head=temp;
so the function invokes undefined behavior.
The function can look like
void display()
{
for ( node * temp = head; temp != nullptr; temp = temp->next )
{
cout << temp->data << "\t";
}
}
Or it is better to define it the following way
std::ostream & display( std::ostream &os = std::cout )
{
for ( node * temp = head; temp != nullptr; temp = temp->next )
{
os << temp->data << "\t";
}
return os;
}
The data member insert_end is also wrong. It does not take into account that head and tail can be equalto nullptr and does not change them.
The function can be defined the following way
void insert_end(int value)
{
node *newnode = new node { value, nullptr };
if ( tail == nullptr )
{
head = tail = newnode;
}
else
{
tail = tail->next = newnode;
}
}
The member function delete_node firstly does not make sense for a singly-linked list and again is wrong and invokes undefined behavior. The function should remove the first node from the list.
Nevertheless if you want to remove the last node from the list then the function can look like
void delete_node()
{
if ( head != nullptr )
{
tail = nullptr;
node *current = head;
while ( current->next )
{
tail = current;
current = current->next;
}
if ( tail == nullptr )
{
head = tail;
}
else
{
tail->next = nullptr;
}
delete current;
}
}
For starters, display() is wrong. You want the update to be temp = temp->next; and it can also be initialized as node * temp = head hence not requiring the second line.
Your delete_node() can be re-written to:
if (head->next == NULL) // handles the case that it consists of 1 element
{
delete head;
head = NULL;
}
else
{
node *nextToEnd = head;
node *end = head->next;
while (end->next != NULL)
{
nextToEnd = end;
end = end->next;
}
delete end;
nextToEnd->next = NULL;
}
As stated in the comments, review the use of the new keyword

C++ Pointers, Linked List Confusion

I am trying to build a linked list in C++. My understanding is that the code I have created should create a node and then progressively link 4 more onto the end. Unfortunately, while I would expect to see the cout results as "12 123 1234 12345" I'm seeing "12 12 12 12" and in my main I am unable to traverse the list - it just crashes.
I have the following code:
struct listNode {
int val;
listNode* next;
};
int nodeCount = 0;
listNode* addToEnd(listNode* node) {
listNode* newNode = new listNode;
newNode->val = ++nodeCount;
newNode->next = NULL;
if (node == NULL) {
return newNode;
}
listNode* current = node;
cout<<"\n\n";
do {
if (current->next == NULL) {
current->next = newNode;
}
cout<<current->val<<"\n";
current = current->next;
} while (current->next != NULL);
cout<<current->val<<endl;
}
int main()
{
listNode* first = addToEnd(NULL);
addToEnd(first);
addToEnd(first);
addToEnd(first);
addToEnd(first);
cout<<"Third: "<<first->next->next->val;
}
Any help is appreciated, as I am at wit's end!
It is obvious that function addToEnd is wrong
listNode* addToEnd(listNode* node) {
listNode* newNode = new listNode;
newNode->val = ++nodeCount;
newNode->next = NULL;
if (node == NULL) {
return newNode;
}
listNode* current = node;
cout<<"\n\n";
do {
if (current->next == NULL) {
current->next = newNode;
}
cout<<current->val<<"\n";
current = current->next;
} while (current->next != NULL);
cout<<current->val<<endl;
}
Let's assume that the list already contains two nodes and consider the do-while loop inside the function. At first current_next != null so the following statement is executed
current = current->next;
Now current points to the second node. Its data member next is equal to NULL. So the condition of the loop
} while (current->next != NULL);
will be false and no iteration will be repeated. So we added nothing.
Also the function returns nothing if node is not equal to NULL.
Rewrite the function the following way
listNode* addToEnd( listNode* node )
{
listNode* newNode = new listNode { ++nodeCount, NULL };
if ( node == NULL) return newNode;
listNode* current = node;
while ( current->next != NULL ) current = current->next;
current->next = newNode;
return newNode;
// or
//return node;
}
Take into account that this statement
cout<<"Third: "<<first->next->next->val;
outputs only the value of the third node.
If you want to output all the list you should write
for ( listNode *current = first; current; current = current->next )
{
std::cout << current->val << ' ';
}
std::cout << std::endl;
By the way using my function you could write in main for example the following way:)
listNode* first;
addToEnd( addToEnd( addToEnd( addToEnd( first = addToEnd( NULL ) ) ) ) );
Use a for loop to get you to the last node instead of a while, and then assign the new node OUTSIDE of the loop. Trying to do it inside will result in an infinite loop (and make the code harder to read):
listNode* current;
for(current = node; current->next != NULL; current = current->next) ;
current->next = newNode;
You're also forgetting to return newNode at the end of the function.
You're falling off the end of a function with non-void return type. The fact that you don't use the return value does not make that ok.
6.6.3 in the Standard says that:
Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.
There is no return statement just in case the if condition that checks if(node==null) fails..
Is it against the rules to use recursive functions in your question?
Why not do...
void addToEnd(listNode* node){
if(node == NULL){
*node = new listNode;
node->next = NULL;
node->val = ++nodeCount;
}else{
addToEnd(node->next);
}
return;
}
int main(){
listNode* first = NULL;
addToEnd(first); // 1
addToEnd(first); // 2
addToEnd(first); // 3
addToEnd(first); // 4
addToEnd(first); // Linked list is now 5 long
}
This is how I would have coded adding five nodes to a linked list that holds a node count. If anyone has advice it is welcome.
#include <iostream>
#include <cstdlib>
using namespace std;
struct listNode{
int val;
listNode* next;
};
listNode* addToEnd(listNode*, int);
int main()
{
listNode* first = NULL;
listNode* temp;
int nodeCount = 1;
for(int i = 0; i < 5; i++){
first = addToEnd(first, nodeCount);
nodeCount++;
}
temp = first;
while(temp){
cout << temp->val << ' ';
temp = temp->next;
}
temp = first;
//Deallocate memory
while(temp){ //could do memory deallocation while displaying
nodeToDelete = temp; //the value of nodeCount but wanted to illustrate
//both methods individually
temp = temp->next;
delete nodeToDelete;
}
first = NULL; //eliminate hanging pointer
return 0;
}
listNode* addToEnd(listNode* node, int nodeCount)
{
listNode* newNode = new (nothrow) listNode;
listNode* current = node;
if(newNode){
newNode->val = nodeCount;
newNode->next = NULL;
if (node == NULL)
node = newNode;
else{
while (current->next != NULL)
current = current->next;
current->next = newNode;
}
}
else
cout << "error allocationg memory" << endl;
return node;
}