diff --git a/README.md b/README.md index 37834c8..2e0219e 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ ## Comparison with wc. -The GNU utils version ([github](https://github.com/coreutils/coreutils/tree/master/src/wc), [savannah](http://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=blob;f=src/wc.c;hb=HEAD)) is a bit over 1K lines of C. It does many things and checks many possible failure modes. +The GNU utils version ([github](https://github.com/coreutils/coreutils/tree/master/src/wc.c), [savannah](http://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=blob;f=src/wc.c;hb=HEAD)) is a bit over 1K lines of C. It does many things and checks many possible failure modes. The busybox version ([git.busybox.net](https://git.busybox.net/busybox/tree/coreutils/wc.c)) of wc is much shorter, at 257 lines, while striving to be [POSIX-compliant](https://pubs.opengroup.org/onlinepubs/9699919799/), meaning it has flags. @@ -35,4 +35,4 @@ The plan9port version of wc ([github](https://github.com/9fans/plan9port/blob/ma - If it doesn't have arguments, read from stdin. - [ ] Open files, read characters. - [ ] Write version that counts lines -- [ ] +- [ ] Document reading from user-inputed stdin (end with Ctrl+D) diff --git a/ww b/ww index 9f8de9b..2ad1347 100755 Binary files a/ww and b/ww differ diff --git a/ww.c b/ww.c index 1bd42fd..2d969a1 100644 --- a/ww.c +++ b/ww.c @@ -1,50 +1,47 @@ #include #include -int process_fn(int fn) +int wc(FILE* fp) { char c[1]; - int seen_word = 0; - int seen_sep_after_word = 0; - int num_words = 0; + int seen_word = 0, seen_sep_after_word = 0, num_words = 0; + int fn = fileno(fp); 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; + if (*c == '\n' || *c == ' ' || *c == '\t') { + 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 + seen_word = 1; } + // exercise: what happens if you only track seen_sep, + // instead of seen_sep_after_word? + // test with: $ echo " hello world" | ./wc if (seen_word && seen_sep_after_word) { num_words++; seen_sep_after_word = seen_word = 0; } } - if (seen_word) { - num_words++; - } + num_words+=seen_word; printf("%i\n", num_words); return 0; } int main(int argc, char** argv) { - if (!isatty(STDIN_FILENO)) { - return process_fn(STDIN_FILENO); + if (argc == 1) { + return wc(stdin); } else if (argc > 1) { FILE* fp = fopen(argv[1], "r"); if (!fp) { perror("Could not open file"); return 1; } - fclose(fp); - return process_fn(fileno(fp)); + return wc(fp) && fclose(fp); } else { printf("Usage: ww file.txt\n"); printf(" or: cat file.txt | ww\n"); + printf(" or: ww # read from user-inputted stdin\n"); } return 0; }