Jack W.
Jack W.

Reputation: 9

Problems with pointers in c - linked list

This is my code (working on a linked list):

typedef struct node {
   int data;
   struct node_t* next;
} node_t;

typedef struct list{
   node_t* head;
} list_t;

node_t* create_node(void){
   node_t* tmp = malloc(sizeof(node_t));
   if (tmp == NULL){
      fprintf(stderr, "Error while allocating memory for node\n");
      exit(EXIT_FAILURE);
   }
   return tmp;
}

void list_insert(list_t* list, node_t* node, int data){
   if (node == NULL){
      node_t* new = create_node();
      new->next = list->head;
      list->head = new;
      new->data = data;
   }
   else{
      node_t* current = list->head;
      while(current != node){
         current = current->next;
      }
      node_t* new = create_node();
      new->next = current->next;
      current->next = new;
      new->data = data;
   }
}

I do get some warnings in list_insert function, but I cannot figure out the reason for them. This function should insert a new node at the beginning, if the node passed as argument is NULL, otherwise it should insert a new node after the node passed as argument.

In this snippet:

if (node == NULL){
   node_t* new = create_node();
   new->next = list->head;
   list->head = new;
   new->data = data;
}

the assignment new->next = list->head; is not correct. Any guesses?

Upvotes: 0

Views: 64

Answers (2)

bruno
bruno

Reputation: 32586

you do not need typedef struct list{ ...}, you just need a variable of type node_t * always containing the head of the list, NULL while it is empty.

For instance :

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

typedef struct node {
  int data;
  struct node * next;
} node_t;

node_t* create_node(int data)
{
  node_t* tmp = malloc(sizeof(node_t));

  if (tmp == NULL){
    fprintf(stderr, "Error while allocating memory for node\n");
    exit(EXIT_FAILURE);
  }
  tmp->data = data;
  tmp->next = NULL;
  return tmp;
}

void list_append(node_t ** l, node_t* node){
  if (*l == NULL) {
    *l = node;
  }
  else {
    while ((*l)->next != NULL)
      l = &(*l)->next;

    (*l)->next = node;
  }
}

/* l, *l, where and node must not be NULL */
int list_insert(node_t ** l, node_t* where, node_t* node) {
  if (*l != where) {
    for (;;) {
      if (*l == NULL)
        return 0;
      l = &(*l)->next;
      if (*l = where)
        break;
    }
  }

  node->next = *l;
  *l = node;
  return 1;
}

void pr(node_t * l)
{
  printf("list is :");
  while (l != NULL) {
    printf(" %d", l->data);
    l = l->next;
  }
  putchar('\n');
}

void clear(node_t ** head)
{
  node_t * l = *head;

  while (l != NULL) {
    node_t * n = l->next;
    free(l);
    l = n;
  }

  *head = NULL;
}

int main()
{
  node_t * head = NULL;
  node_t * n3 = create_node(3);

  list_append(&head, create_node(1));
  list_append(&head, n3);
  pr(head);

  list_insert(&head, n3, create_node(2));
  pr(head);  

  list_insert(&head, head, create_node(0));
  pr(head);

  clear(&head);
  pr(head);

  return 0;
}

I changed the creation to be able to give the data at that time, this is more clear (like a constructor in C++)

Compilation and execution :

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra c.c
pi@raspberrypi:/tmp $ ./a.out
list is : 1 3
list is : 1 2 3
list is : 0 1 2 3
list is :
pi@raspberrypi:/tmp $ valgrind ./a.out
==27963== Memcheck, a memory error detector
==27963== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==27963== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==27963== Command: ./a.out
==27963== 
list is : 1 3
list is : 1 2 3
list is : 0 1 2 3
list is :
==27963== 
==27963== HEAP SUMMARY:
==27963==     in use at exit: 0 bytes in 0 blocks
==27963==   total heap usage: 5 allocs, 5 frees, 1,056 bytes allocated
==27963== 
==27963== All heap blocks were freed -- no leaks are possible
==27963== 
==27963== For counts of detected and suppressed errors, rerun with: -v
==27963== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)

Upvotes: 1

dbush
dbush

Reputation: 223699

In your definition of struct node:

typedef struct node {
        int data;
        struct node_t* next;
    } node_t;

You define next as a pointer to struct node_t, but there is no such type. You want struct node:

typedef struct node {
        int data;
        struct node* next;
    } node_t;

Upvotes: 1

Related Questions