/*

 * obs_list.c

 * This program reads a sequence of observations (real numbers), computes

 * their statistics and prints the deviation of each observation from the

 * average.

 */

 

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <math.h>

 

#define MAX_STRING 40

 

struct _Observation

{

  double              value;    /* The observation value. */

  struct _Observation *p_next;  /* Points to the next observation. */

};

 

typedef struct _Observation Observation;

 

int main ()

{

  char        in[MAX_STRING];

  Observation *p_first = NULL;  /* The first observation. */

  Observation *p_last = NULL;   /* The last observation so far. */

  Observation *p_curr = NULL;   /* The current observation. */

  int         n_obs = 0;        /* Nunber of observations so far. */

  double      sum_obs = 0;      /* The sum of all observations. */

  double      sum_sqr_obs = 0;  /* The sum of their squares. */

  double      mean;             /* The mean observation. */

  double      std_dev;          /* The standard deviation. */

  int         i;

 

  while (1)

  {

    /* Read the current user input. */

    printf ("Please enter an observation (or . to quit): ");

    scanf ("%s", in);

 

    /* Stop in case of a "." input. */

    if (strcmp(in, ".") == 0)

      break;

 

    /* Create a new observation. */

    p_curr = (Observation *) malloc (sizeof(Observation));

    p_curr->value = atof (in);

    p_curr->p_next = NULL;

 

    /* Update sums. */

    n_obs++;

    sum_obs += p_curr->value;

    sum_sqr_obs += (p_curr->value)*(p_curr->value);

 

    /* Make it the last observation. */

    if (p_last != NULL)

    {

      /* Link p_curr after p_last and update the p_last pointer. */

      p_last->p_next = p_curr;

      p_last = p_curr;

    }

    else

    {

      /* No observations so far: p_curr is the first and last one. */

      p_first = p_curr;

      p_last = p_curr;

    }

  }

 

  /* Stop here if there are no observations. */

  if (n_obs == 0)

  {

    printf ("No observations.\n");

    return (0);

  }

 

  /* Compute the mean and standard deviation of all observations. */

  mean = sum_obs / n_obs;

  std_dev = sqrt (sum_sqr_obs / n_obs - mean*mean);

 

  printf ("Mean of all observations: %g, standard deviation: %g\n",

          mean, std_dev);

 

  /* Go over all observations and print their deviations from the mean. */

  p_curr = p_first;

  i = 1;

 

  while (p_curr != NULL)

  {

    printf ("Observation no. %d: %g (%g*sigma).\n",

            i, p_curr->value, (p_curr->value - mean) / std_dev);

 

    /* Move to the next observation. */

    i++;

    p_curr = p_curr->p_next;

  }

 

  /* Free memory. */

  while (p_first != NULL)

  {

    /* Keep a pointer to the second observation. */

    p_curr = p_first->p_next;

 

    /* Free the first observation. */

    free (p_first);

 

    /* Update the pointer to the first observation. */

    p_first = p_curr;

  }

 

  return (0);

}