#include #include #include #include #include // THINGS WE SHOULD COUNT typedef struct { int bytes; int lines; int longest; int words; } COUNTS; // ------------------------------------------------------------------------ void report_counts(COUNTS what, char *filename) { // JUST DISPLAY THE REQUESTED COUNTS printf("%8d", what.lines); printf("%8d", what.words); printf("%8d", what.bytes); printf("%8d", what.longest); // ONLY DISPLAY THE FILENAME IF IT'S NOT NULL if(filename != NULL) { printf("\t\t%s", filename); } printf("\n"); } void counter(FILE *fp, char *filename) { COUNTS this = { 0, 0, 0, 0 }; char line[BUFSIZ]; // FOREACH LINE READ FROM THE FILE-POINTER.... while( fgets(line, sizeof line, fp) != NULL) { int len = 0; bool inside_word = false; char *s = line; ++this.lines; // UNTIL WE HAVE REACHED THE END OF THIS LINE.... while(*s) { ++this.bytes; // FOR THE LONGEST LINE, TABS ARE EXPANDED TO A MULTIPLE OF 8 SPACES if(*s == '\t') { len = (len+8) / 8 * 8; } else if(*s != '\n') { ++len; } // KEP TRACK OF WHETHER WE'RE INSIDE A WORD, OR NOT if(inside_word && isspace(*s)) { inside_word = false; } else if(!inside_word && !isspace(*s)) { ++this.words; inside_word = true; } // 'WALK' ALONG THE LINE ++s; } // SEE IF WE'VE FOUND A NEW LONGEST LINE if(this.longest < len) { this.longest = len; } } report_counts(this, filename); } // ------------------------------------------------------------------------ // PROVIDE A 'USAGE' MESSAGE IF AN INVALID SWITCH PROVIDED void usage(char *argv0) { fprintf(stderr, "Usage: %s [-clLw] [file ...]\n", argv0); exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { // ARGUMENTS PROVIDED, ITERATE OVER EACH TREATING IT AS A FILENAME for(int a=1 ; a