/*

 * grades_3.c

 * This program reads a number of grades, and computes statistics about them.

 * The number of grades is unlimited.

 */

 

#include <stdio.h>

#include <math.h>

 

/* Prototypes: */

void comp_statistics (const int *arr, int n,

                      float *average, float *std_dev);

 

int main ()

{

  const int min_grade = 0;

  const int max_grade = 100;

  int       n_grades;          /* The number of grades. */

  int       *grades;           /* The grades. */

  int       count;             /* The number of grades currently read. */

  int       curr_grade;        /* The current grade. */

  float     average;           /* The average grade. */

  float     std_dev;           /* The standard deviation from the average. */

  int       n_above_avg;       /* Number of grades above the average. */

  int       i;

 

  /* Read the number of grades. */

  do

  {

    printf ("Please enter the number of grades: ");

    scanf ("%d", &n_grades);

  } while (n_grades < 0);

 

  /* Allocate memory. */

  grades = (int *) malloc (sizeof(int) * n_grades);

 

  /* Read the grades on by one. */

  count = 0;

  while (count < n_grades)

  {

    printf ("%d) Please enter the next grade: ", count + 1);

    scanf ("%d", &curr_grade);

   

    if (curr_grade < min_grade || curr_grade > max_grade)

    {

      printf ("Ignoring illegal grade (%d).\n", curr_grade);

      continue;

    }

 

    /* Store the grade. */

    grades[count] = curr_grade;

    count++;

  }

 

  /* Print out the grades and the statistics about them. */

  printf ("\nThe grades: \n");

  for (i = 0; i < n_grades; i++)

    printf ("%d ", grades[i]);

  printf ("\n");

 

  comp_statistics (grades, n_grades,

                   &average, &std_dev);

 

  printf ("Average grade is %g (dev = %g).\n", average, std_dev);

 

  /* Find how many students have a grade which is above the average. */

  n_above_avg = 0;

  for (i = 0; i < n_grades; i++)

  {

    if (grades[i] > average)

      n_above_avg++;

  }

 

  /* Note that we make sure that our output is grammatically correct: */

  printf ("%d student%s above the average.\n",

          n_above_avg,

          (n_above_avg == 1) ? " is" : "s are");

 

  /* Free memory. */

  free (grades);

 

  return (0);

}

 

/* ------------------------------------------------------------------------

 * Function: comp_statistics

 * Purpose : Compute the average and standard deviation of an array of

 *           integers.

 * Input   : arr     - The array.

 *           n       - Its size.

 * Output  : average - The average.

 *           std_dev - The standard deviation.

 * Returns : Nothing.

 */

void comp_statistics (const int *arr, int n,

                      float *average, float *std_dev)

{

  int       sum = 0;           /* The sum of all elements so far. */

  int       sum_sqrs = 0;      /* The sum of their squares. */

  float     variance;

  int       i;

 

  for (i = 0; i < n; i++)

  {

    sum += arr[i];

    sum_sqrs += arr[i]*arr[i];

  }

 

  /* Compute the average and variance,

     using the equality: Var(X) = E(X^2) - E(X)*E(X) */

  *average = (float)sum / (float)n;

 

  variance = (float)sum_sqrs / (float)n - (*average)*(*average);

 

  /* Compute the standard deviation. */

  *std_dev = sqrt(variance);

 

  return;

}