Listing 1 Filtering by repeatedly discarding outliers

#include <stdio.h>
#include <stdlib.h>  /* for strtol(), qsort() */

#define AVGTHRESH 2    /* How many numbers to keep before averaging (>= 2) */

static int
intcmp(const void *pa, const void *pb)
{
       int const a = *(int const *)pa, b = *(int const *)pb;

       return (a < b) ? -1 : (a > b) ? 1 : 0;
}

int
main(int argc, char **argv)
{
       int i;
       imt high, low;
       long l, t;
       char *p;
       int buf[100];

       /* Read in input (for now, taken from the command line) */
       if (argc < 2) {
              fprintf(stderr, "Usage: %s number number...\n", argv[0]);
              return 1;
       }

       if (argc > sizeof(buf)/sizeof(*buf) + 1)
              argc = sizeof(buf)/sizeof(*buf) + 1;
       printf("Input: ");
       for (high = 1; high < argc; high++) {
              p = argv[high];
              if (!*p || (l = strtol(p, &p, 0), *p) || (int)l != l) {
                     putchar('\n');
                     fprintf(stderr, "%s: Illegal argument \"%s\": integer expected\n", argv[0], argv[high]);
                     return 1;
              }
              printf(" %d" , (int)l);
              buf[high-1] = (int)l;
       }
       putchar('\n');


       /* Put the data into sorted order and compute an overall sum */
       --high; /* Upper bound */

       qsort(buf, high, sizeof(*buf), intcmp);

       l = 0;
       for (i = 0; i < high; i++)
              1 += buf[i];    /* Compute sum */

       /* The main filtering loop: keep casting out outliers */
       low = 0;        /* Lower bound */

       /* Loop invariant: l is the sum from buf[low] through buf[high-1]. */
       while (high-low > AVGTHRESH) {
              /* These computations are perhaps a bit too clever */
#if MEAN
              t = ((long)buf[low] + buf[high-1])*(high-low) - 1*2;
#else /* median */
              t = buf[low] + buf[high-1] - buf[(high+low)/2] - buf[(high+low-1)/2];
#endif
              /* Note that if both are equidistant, we throw out *both* */
              if (t >= 0)
                     l -= buf[--high]; /* high is further from the avg. */
              if (t <= 0)
                     l -= buf[low++]; /* low is further from the avg. */
              /* For illustration, print the buffer each time */
              for (i = low; i < high; i++)
                     printf("%d%c", buf[i], i == high-1 ? '\n' : ');
       }
       /* Return the average of what remains in the buffer */
       printf("The final average value is %ld.\n", l / (high-low));

       return 0;
}