home *** CD-ROM | disk | FTP | other *** search
- 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
- cow
- dog
- fox
- jumped
- jumped
- lazy
- moon
- over
- over
- quick
- the
- the
- the
- the
- */
-
-