Search code examples
c++linked-listdynamic-memory-allocationinsertion

Segfault while inserting node at mid of a linked list in c++


I am creating a simple singly linked list and trying to insert a node at start, mid and end of the list. But my 'insertAtMid' is not working properly and its crashes the program with error; "Exception occurred. Segmentation fault." Here is the whole program :

/*
    Write a program that creates a singly linked list until user wants and displays it. then insert a node at the beginning, middle, and end of the list.
*/
#include <iostream>
using namespace std;
struct node
{
    int data;
    node *next;
};
class linkedList
{
private:
    node *head, *tail;

public:
    linkedList()
    {
        head = NULL;
        tail = NULL;
    }
    void addNode()
    {
        int item;
        cout << "Enter data for node : ";
        cin >> item;
        node *temp = new node();
        temp->data = item;
        temp->next = NULL;
        if (head == NULL)
        {
            head = temp;
            tail = temp;
        }
        else
        {
            tail->next = temp;
            tail = tail->next;
        }
    }
    node *getHead()
    {
        return head;
    }
    static void display(node *head)
    {
        int i = 1;
        while (head != NULL)
        {
            cout << "Node " << i << " : " << head->data << endl;
            head = head->next;
            i++;
        }
    }
    void insertAtBegining()
    {
        int n;
        cout << "Enter data you want to insert : ";
        cin >> n;
        node *temp = new node();
        temp->data = n;
        temp-> next = head;
        head = temp;
        cout << "Inserted Successfully. Updated list is : "<<endl;
    }
    static void insertAtMid(node * head)
    {
        int n, length=0, middle;
        while (head!=NULL)
        {
           length ++;
           head = head->next;
        }
        middle = length/2;
        while((middle --) > 1)
        {
            head = head->next;
        }
        cout << "Enter data you want to insert : ";
        cin >> n;
        node *temp = new node();
        temp->data = n;
        temp->next = head->next;
        head = temp;
        cout << "Inserted Successfully. Updated list is : "<<endl;
    }
};
int main()
{
    linkedList l1;
    char choice;
    int menuChoice;
    cout << "List is not created yet, please add data to create the list." << endl;
    do
    {
        l1.addNode();
        cout << "Node added. Want to add another node (Y/N) : ";
        cin >> choice;
    } while (choice == 'y' || choice == 'Y');
    cout << "List created successfully. Select from options below : "<<endl;
    cout << "1. Display list \n2. Insert at Begining \n3. Insert at Mid \n4. Insert at End \n5. exit"<<endl;
    cin >> menuChoice;
    switch(menuChoice)
    {
        case 1:
            linkedList::display(l1.getHead());
            break;
        case 2:
            l1.insertAtBegining();
            linkedList::display(l1.getHead());
            break;  
        case 3:
            l1.insertAtMid(l1.getHead());
            linkedList::display(l1.getHead());
            break;
        case 4:
            l1.addNode();
            cout << "Successfully inserted node at end of list. Updated list is :"<<endl;
            linkedList::display(l1.getHead());
            break;  
        case 5:
            exit;
            break;
        default:
            cout << "Invalid selection...!!";            
    }
}

The compiler is showing that the error is at line 85 and segmentation error has occurred there. here is the Screenshot of error: Exception has occurred


Solution

  • According to your instance of code, you are counting the number of nodes and you are moving the head pointer till the end of the list.

    Before the below statement gets executed, the head will be at currently pointing the last node.

    while((middle --) > 1)
            {
                head = head->next;
            }
    

    As soon as this statement head = head->next; gets executed, then head will point to nowhere, or you could say, its pointing to NULL. That is the reason you are getting an segmentation error, cause head->next tries to give a reference to an address, which is an garbage. Nothing exists there.

    Instead using head to iterate, use a temporary node, assign it to head and then count the length of the list.

       node *tmp = new node();
       tmp = head;
       int length = 0;
       while(tmp != NULL){
           length++;
           tmp = tmp->next;
       }
    
       middle = ((length % 2) == 0) ? (length /2 ) : (length + 1)/2);
       tmp = head;
       while((middle --) > 1){
            tmp = tmp->next;
       }
     
       cout << "Enter data you want to insert : ";
       cin >> n;
       node *curr = new node();
       curr->data = n;
       curr->next = temp->next;
       temp->next = curr;
    

    I would suggest you not to use the head pointer, for iterating, as it may lead to dangling reference.