Search code examples
calgorithmdata-structureswhile-loopdoubly-linked-list

Appending node to the end of a linked list in C; infinite loop problem


dlistint_t *add_dnodeint_end(dlistint_t **head, const int n)
{
     dlistint_t *head_ref, *new;

     new = malloc(sizeof(dlistint_t);
     if (!new)
          return (NULL);

     new->n = n;
     new->next = NULL;
     new->prev = NULL;

     if (!(*head))
     {
          *head = new;
          return (new);
     }

     head_ref = *head;
     while (head_ref)
     {
          if (!head_ref->next)
          {
               head_ref->next = new;
               new->prev = head_ref;
               /* I need clarity here */
               head_ref = head_ref->next;
          }
          head_ref = head_ref->next;
     }
     return (new);
}

The function adds a new node to the end of a doubly linked list but my problem is with the if block in while loop. If i remove the line head_ref = head_ref->next; the while loop runs infinitely. When i use a break; statement, it doesn't work for all cases. My confusion now is that I expect the head_ref = head_ref->next; statement outside the if block to always execute even when the if-condition is met thus terminating the loop.

I thought to ask because i did not find an answer that explains this clearly. Please link me if you find any that explains this well.


Solution

  • Where you have the comment /* I need clarity here */, there should be a return new; (or you should break out of the loop) as without it you'll make head_ref NULL with head_ref = head_ref->next and then the next (same) statement will make an invalid reference.

    If is more natural to remove that if block and put that logic after the loop, and have the loop condition such that it ends when you're at the tail node.

    I would not call this variable head_ref, because it stops being that "head" once you start looping. Maybe call it current:

    dlistint_t *add_dnodeint_end(dlistint_t **head, const int n)
    {
         dlistint_t *current, *new;
    
         new = malloc(sizeof(dlistint_t)); // missing parenthesis
         if (!new)
              return NULL;
    
         new->n = n;
         new->next = NULL;
         new->prev = NULL;
    
         current = *head;
         if (current == NULL)
         {
              *head = new;
              return new;
         }
    
         while (current->next != NULL)  // Exit loop when at tail
         {
              current = current->next;
         }
         current->next = new;
         new->prev = current;
         return new;
    }