Search code examples
clinked-listdynamic-memory-allocation

Errors in insert at back for linked list


I am making an attempt to build my library of elementary operations for linked list but I get into trouble with the function push_back() which works: Push the data at the end of the linked list. Here is my source code:

node* push_back(node *dir, item datain)
{
    node *newnode = (node *)malloc(sizeof(node));
    newnode->data = datain;
    newnode->next = NULL;
    if (dir == NULL)
    {
        dir = newnode;
    }
    else
    {
        while (dir->next != NULL)
            dir = dir->next;
        dir->next = newnode;
    }
    return dir;
}
void printlist(node *dir)
{
    printf("%-50s%-50s%-20s\n", "Name", "Email", "Phone number");
    while (dir != NULL)
    {
        item temp = dir->data;
        printf("%-50s%-50s%-20s\n", temp.name, temp.email, temp.phone);
        dir = dir->next;
    }
}
int main()
{
    node *dir = (node *) malloc(sizeof(dir));
    dir = NULL;
    int i = 0;
    while(i<3)
    {
        item temp = userdata();
        dir = push_back(dir, temp);
        i++;
    }
    printlist(dir);
    freelist(dir);
    return 0;
}

My problem: If I just insert 2 records (each record has name, email and phone number), then it's ok. However, If there are more than 2 records, as I print the whole records I have inserted, it just print out the two lastest record. I have checked my code on some websites but I find that they bare no resemblance as mine. For example:

INPUT:

Enter the name: Joey

Enter the email: [email protected]

Enter the phone number: 0235632514

Enter the name: Mathew

Enter the email: [email protected]

Enter the phone number: 012502252

Enter the name: Waley

Enter the email: [email protected]

Enter the phone number: 036625125

OUTPUT:

Name Email Phone number

Mathew [email protected] 012502252

Waley [email protected] 036625125


Solution

  • First problem :

     node *dir = (node *) malloc(sizeof(dir));
     dir = NULL;
    

    so you have a memory leak because you loose the allocation, just do

    node *dir = NULL;
    

    Second problem push_back returns the last element of the list so doing

    dir = push_back(dir, temp);
    

    dir now point to the last element and you lost the head of the list, so all elements except the last

    One way is to modify push_back to return the (new) head of the list :

    node* push_back(node * head, item datain)
    {
        node *newnode = (node *)malloc(sizeof(node));
    
        newnode->data = datain;
        newnode->next = NULL;
    
        if (head == NULL)
            return newnode;
    
        node * dir = head;
    
        while (dir->next != NULL)
           dir = dir->next;
        dir->next = newnode;
    
        return head;
    }
    

    but that supposes the caller always does something like dir = push_back(dir, temp);

    an other way is to use double pointer :

    void push_back(node ** head, item datain)
    {
        node *newnode = (node *)malloc(sizeof(node));
    
        newnode->data = datain;
        newnode->next = NULL;
    
        if (*head == NULL)
            *head = newnode;
        else {
          node * dir = *head;
    
          while (dir->next != NULL)
             dir = dir->next;
          dir->next = newnode;
        }
    }
    

    and the caller can just do push_back(&dir, temp); without taking the risk to forget to assign