/* file: pbs-or.c G. Moody 25 February 2012 Read N sorted files, write lines in any of them (logical "or") */ #include #include #include #define LMAX 128 char **line, *pline; FILE **ifile; int n; /* cleanup: close input files, free allocated memory, and quit. */ void cleanup() { while (n-- > 0) { fclose(ifile[n]); free(line[n]); } free(line); free(ifile); exit(0); } /* init: open input files and read the first line of each. Ignore unreadable and empty files, since they will not contribute to the output. */ void init(int argc, char **argv) { if (argc < 3) exit(1); argc--; argv++; /* skip argv[0] */ ifile = (FILE **)calloc(argc, sizeof(FILE *)); line = (char **)calloc(argc, sizeof(char *)); for (n = 0; n < argc; n++) { if ((ifile[n] = fopen(argv[n], "r")) == NULL) { argc--; argv++; n--; continue; } line[n] = (char *)calloc(LMAX, sizeof(char)); if (fgets(line[n], LMAX, ifile[n]) == NULL) { argc--; argv++; fclose(ifile[n--]); continue; } } pline = (char *)calloc(LMAX, sizeof(char)); } main(int argc, char **argv) { init(argc, argv); while (n > 0) { int i, j; for (i = 0, j = 1; j < n; j++) if (strcmp(line[i], line[j]) > 0) i = j; /* line[i] is the (lexicographically) smallest input line remaining */ if (strcmp(line[i], pline)) { /* output only if not already written */ fputs(line[i], stdout); strcpy(pline, line[i]); } /* get the next line from ifile[i] */ if (fgets(line[i], LMAX, ifile[i]) == NULL) { /* if there is nothing left in ifile[i], close it */ fclose(ifile[i]); free(line[i]); /* move the last open input into the slot just vacated */ if (i < --n) { ifile[i] = ifile[n]; line[i] = line[n]; } } } /* when there are no more open inputs, we're done! */ cleanup(); }