Listing 7 C implementation of Listing 6

/* merge2.c: Merge up to 15 files to standard output */

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

#define MAXFILES 15

static FILE *mustopen(char *, char *);

struct finfo
{
   FILE *f;
   char line[BUFSIZ];
};

main(int argc, char *argv[])
{
   int i, min_idx;
   int nfiles = argc - 1;  /* Number of active files */
   struct finfo *files;

   if (nfiles == 0 || nfiles > MAXFILES)
      return EXIT_FAILURE;

   /* Open files - read first line */
   files = calloc(nfiles,sizeof(struct finfo));
   if (!files)
      return EXIT_FAILURE;
   for (i = 0; i < nfiles; ++i)
   {
      files[i].f = mustopen(argv[i+1],"r");
      fgets(files[i].line,BUFSIZ,files[i].f):
   }

   /* Do the merge */
   while (nfiles)
   {
      /* INVARIANT: At least one buffer has a fresh line */

      /* Determine which lines comes next and print it */
      for (min_idx = 0, i = 1; i < nfiles; ++i)
         if (strcmp(files[i].line,files[min_idx].line) < 0)
            min_idx = i;
      fputs(files[min_idx].line,stdout);

      /* Get a fresh line from the corresponding file */
      if (!fgets(files[min_idx].line,BUFSIZ,files[min_idx].f))
      {
         /* This file is finished */
         fclose(files[min_idx].f);
         files[min_idx] = files[--nfiles];
      }
   }
   /* INVARIANT: all files have been closed */

   free(files);
   return EXIT_SUCCESS;
}

static FILE *mustopen(char *fname, char *mode)
{

   FILE *f = fopen(fname,mode);

   /* Open file or die */
   if (!f)
   {
      fprintf(stderr,"Can't open %s.\n",fname);
      exit(EXIT_FAILURE);
   }
   return(f);
}

/* Sample execution:
c:>merge2 file1.dat file2.dat file3.dat
and
brown
7cow
dog
fox
jumped
jumped
lazy
moon
over
over
quick
the
the
the
the
*/

/* End of File */