#include #include #include /* Track whether we are inside or outside a word */ typedef enum _state {IN,OUT} state; /* true if c is a 'word' character (not a blank, space, or a tab) */ static bool is_word(char c) { return c != ' ' && c != '\t' && c != '\n'; } struct res { uint32_t cc; uint32_t lc; uint32_t wc; }; struct res_internal { struct res res; state s; }; static struct res_internal nri(void) { struct res_internal res = { .s = OUT, .res = { .cc = 0, .lc = 0, .wc = 0, } }; return res; } static struct res_internal do_count_internal(FILE* fin, struct res_internal res) { int c = fgetc(fin); if (c == EOF) { return res; } res.res.cc++; if (c == '\n') { res.res.lc++; } if (!is_word(c)) { res.s = OUT; } else if (res.s == OUT) { res.s = IN; res.res.wc++; } __attribute__((musttail)) return do_count_internal(fin, res); } struct res do_count() { struct res_internal ri = do_count_internal(stdin, nri()); return ri.res; } /* Counts characters, lines, and words from stdin. 'characters' are single byte characters. No handling for encodings in c standard lib. 'lines' are newline characters. 'words' are contiguous sequences of characters other than space, tab, newline */ int main(void) { struct res res = do_count(); printf("cc=%d lc=%d wc=%d\n", res.cc, res.lc, res.wc); return 0; }