Search code examples
cstructlinked-listpass-by-referencesingly-linked-list

In a program using linked-list no output is being shown in c


i'm working on a program in c language in which I have to use linked-list and in this program I have to insert the new node at the start of the linked-list if the user pass the value of the place 0 and also insert the new node at the end of the linked-list if the user pass the value of the place 1 in the choice variable. But i'm not getting any output on console and my program ends by just writing Output: I can't figure out the problem in my code and here's my code.

/* 
  program for making nodes and adding them in memory as per 0
  and 1

  0 means that insert the number at front , in other words insert number after head 

  1 means insert number at the last place

  First you need to input a number and then enter the place you want to insert it by giving input as 0 and 1 
  
  *Recall what does 0 and 1 mean by looking at line 5-7 respectively. 
  
  Just like 

  5 0 6 1 7 0 8 1

*/

#include <stdio.h>
#include <stdlib.h>

// declaring struct with typedef for ease of use
typedef struct node
{
  int data;
  struct node *next;
}node;

// declarations of functions use for this program respectively
void free_node(struct node *head);
void insert_at_beg(int num, struct node *head);
void insert_at_end(int num, struct node *head);
void print_node(struct node *head);

int main(void)
{
  struct node *head = NULL;
  int n;
  // taking input
  printf("Input number of nodes: ");
  scanf("%d",&n);

  int num, choice;

  printf("\nInput data for nodes->\n");
  // loop which takes value and choice 
  for (int i = 0; i < n; i++)
  {
    num = 0, choice = 0;
    printf("\nInput data for the %d node: ", i+1);
    scanf("%d",&num);

    do
    {
      printf("Input place for the %d node: ", i+1);
      scanf("%d",&choice);
    }
    while (choice != 1 && choice != 0);
    
    if (choice == 0)
    {
      // function to insert node at front of head
      insert_at_beg(choice, head);

    }
    else 
    {
      // function to insert node at last place
      insert_at_end(choice, head);

    }
  }
  
  // function to print nodes
  print_node(head);
  
  // function to free memory made by malloc()
  free_node(head);
}

// function to free the nodes 
void free_node(struct node *head)
{
  struct node *temp = head;
  while(temp != NULL)
  {
    free(temp);
    temp = temp->next;
  }
}

// function for inserting number at front
void insert_at_beg(int num, struct node *head)
{ 
  struct node *new_node = malloc(sizeof(node));

  if (new_node == NULL)
  {
    printf("Can't allocate memory.");
    exit (1);
  }

  new_node->data = num;  
  new_node->next = head;
  head = new_node;
}

// function for inserting node at end
void insert_at_end(int num, struct node *head)
{
  struct node *new_node, *last_node = NULL;
  new_node = malloc(sizeof(node));

  if (new_node == NULL)
  {
    printf("Can't allocate memory.");
    exit (1);
  }
  if (head == NULL)
  {
    new_node->data = num;
    new_node->next = NULL;
    head = new_node; 
  }
  
  last_node = head;

  new_node->data = num;
  new_node->next = NULL;

  while (last_node->next != NULL)
  {
    last_node = last_node->next;
  } 

  last_node->next = new_node;
}

//function for printing nodes
void print_node(struct node *head)
{
  printf("\nOutput: \n");
  struct node *temp = head;

  while(temp != NULL)
  {
    printf("%d ",temp->data);
    temp = temp->next;
  }
}

Solution

  • You need to pass the pointer to the head node by reference to your functions insert_at_beg and insert_at_end and desirable to the function free_node.

    Passing by reference in C means passing an object indirectly through pointer to it.

    So for example the function insert_at_beg can look the following way. Pay attention to that such a function should not issue any message. It is the caller of the function that decides whether to output a message or not.

    // function for inserting number at front
    int insert_at_beg( struct node **head, int num )
    { 
        struct node *new_node = malloc( sizeof( struct node ) );
        int success = new_node != NULL;
    
        if ( success )
        {
            new_node->data = num;  
            new_node->next = *head;
            *head = new_node;
        }
    
        return success;
    }
    

    Correspondingly the function insert_at_end can look the following way

    // function for inserting node at end
    int insert_at_end( struct node **head, int num )
    {
        struct node *new_node = malloc( sizeof( struct node ) );
        int success = new_node != NULL;
    
        if ( success )
        {
            new_node->data = num;
            new_node->next = NULL;
     
            while ( *head != NULL )
            {
                head = &( *head )->next;
            }
    
            *head = new_node;
        }
    
        return success;
    }
    

    The function free_node has undefined behavior because you are using the pointer temp to access the memory that was already freed.

    free(temp);
    temp = temp->next;
    

    The function can be defined the following way

    // function to free the nodes 
    void free_node( struct node **head )
    {
        while( *head != NULL )
        {
            struct node *temp = *head;
            head = &( *head )->next;
            free( temp );
        }
    }
    

    The functions can be called like

    insert_at_end( &head, num );
    

    or

    if ( !insert_at_end( &head, num ) )
    {
        printf( "There is no enough memory to insert the value %d\n", num );
    }
    

    The parameter of the function print_node should have the qualifier const because the list is not changed within the function

    //function for printing nodes
    void print_node( const struct node *head )
    {
      printf("\nOutput: \n");
      const struct node *temp = head;
      //...