#include #include // read, isatty // STDIN_FILENO int process_fn(int fn) { char c[1]; int seen_word = 0; int seen_sep_after_word = 0; int num_words = 0; while (read(fn, c, sizeof(c)) > 0) { if (*c != '\n' && *c != ' ' && *c != '\t') { seen_word = 1; } else if (seen_word) { seen_sep_after_word = 1; } else { // see a separator, but haven't seen a word: do nothing // exercise: what happens if you only track seen_sep, // instead of seen_sep_after_word? // test with: $ echo " x x" | ./wc } if (seen_word && seen_sep_after_word) { num_words++; seen_sep_after_word = seen_word = 0; } } if (seen_word) { num_words++; } printf("%i\n", num_words); return 0; } int main(int argc, char** argv) { if (!isatty(STDIN_FILENO)) { return process_fn(STDIN_FILENO); } else if (argc > 1) { FILE* fp = fopen(argv[1], "r"); if (!fp) { perror("Could not open file"); return 1; } return process_fn(fileno(fp)); } else { printf("Usage: ww file.txt\n"); printf(" or: cat file.txt | ww\n"); } return 0; }