llwfp

Documentation
Login

Documentation

/*
   Compile:
   readme-ex01e-using-array-of-double
 */

#include <string.h> /* memcpy() */
#include <stdio.h>  /* printf() */
#include <stdlib.h> /* calloc() */

typedef struct node_double_arr_t
{
  struct node_double_arr_t *next;
  double *data;    /* NOT VERY GENERIC */
  size_t arr_len; /* NOT VERY GENERIC */
} node_double_arr_t;

/* Delete data for all but the 3 first nodes, as they contain static data, and should not be free():ed */
void data_cleanup(node_double_arr_t **node)
{
  node_double_arr_t *current = *node;
  while (current)
  {
    free(current->data);
    current = current->next;
  }
}

/* Delete all nodes */
void node_cleanup(node_double_arr_t **head)
{
  node_double_arr_t *current = *head, *next = NULL;
  while (current)
  {
    next = current->next;
    free(current);
    current = next;
  }
   /* Set variable to NULL *before* free(). */
   /* Valgrind doesn't like it the other way around! */
  *head = NULL;
  free(*head);
}

/* Print the array for a node */
void node_print(node_double_arr_t *node, int node_index)
{
  int i = 0;
  printf("node%d->data= {", node_index);
  for (i = 0; i < (int)node->arr_len; ++i)
  {
    if (i) printf(", ");
    printf("%.1f", node->data[i]);
  }
  printf("}\n");
}

int
main(int argc, char *argv[])
{
  node_double_arr_t *node1 = calloc(1, sizeof(*node1));
  node_double_arr_t *node2 = calloc(1, sizeof(*node2));
  node_double_arr_t *node3 = calloc(1, sizeof(*node3));
  node_double_arr_t *node_current = NULL;
  node_double_arr_t *node  = calloc(1, sizeof(*node));
  int i = 0;

  double data1[] = {12.0, 99.0, 37.0};
  double data2[] = {22.0, 98.0, 35.0, 21.0, 97.0, 34.0};
  double data3[] = {32.0, 97.0, 33.0, 31.0, 96.0, 30.0, 36.0, 92.0};

  printf("\nREADME EX01e\n");
  printf("----------------------------------------\n");

  /* Assign data */
  node1->data = data1;
  node1->arr_len = sizeof(data1)/sizeof(data1[0]);
  node2->data = data2;
  node2->arr_len = sizeof(data2)/sizeof(data2[0]);
  node3->data = data3;
  node3->arr_len = sizeof(data3)/sizeof(data3[0]);

  node1->next = node2;
  node2->next = node3;
  node3->next = NULL;

  /* Print the array for each node */
  node_current = node1;
  i = 1;
  while (node_current)
  {
    node_print(node_current, i++);
    node_current = node_current->next;
  }

  /* Create another 100 nodes, link first node to node3 */
  for (i = 0; i < 100; ++i)
  {
    double data[] = {0, 97.0, 33.0, 31.0, 96.0, 30.0, 36.0, 92.0};
    data[0] = (double)i;
    if (i == 0) node3->next = node;
    node->arr_len = sizeof(data)/sizeof(data[0]);
    node->data = calloc(1, sizeof(data));
    memcpy(node->data, data, sizeof(data));
    node->next = calloc(1, sizeof(*node));
    node = node->next;
  }

  /* Print node 45 of 103 - should print "node45->data= {42.0, 97.0, 33.0, 31.0, 96.0, 30.0, 36.0, 92.0}" */
  node = node1;
  for (i = 0; i < 45; ++i)
  {
    node = node->next;
  }
  node_print(node, 45);

  /* Cleanup dynamic data, skipping 3 first nodes */
  data_cleanup(&node3->next);

  /* Delete all nodes */
  node_cleanup(&node1);

  printf("\nTIP: MEMLEAK CHECK:\n");
  printf("valgrind -v --track-origins=yes --leak-check=full --show-leak-kinds=all %s\n", argv[0]);
  (void)argc;

  printf("----------------------------------------\n\n");

  return 0;
}