diff options
Diffstat (limited to 'ex1-10.c')
-rw-r--r-- | ex1-10.c | 66 |
1 files changed, 49 insertions, 17 deletions
@@ -6,31 +6,63 @@ typedef enum _state {IN,OUT} state; /* true if c is a 'word' character (not a blank, space, or a tab) */ -bool is_word(char c) { +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) { - int c; - state s = OUT; - uint32_t cc = 0, lc = 0, wc = 0; - while ((c = getchar()) != EOF) { - cc++; - if (c == '\n') { - lc++; - } - if (!is_word(c)) { - s = OUT; - } else if (s == OUT) { - s = IN; - wc++; - } - } - printf("cc=%d lc=%d wc=%d\n", cc, lc, wc); + struct res res = do_count(); + printf("cc=%d lc=%d wc=%d\n", res.cc, res.lc, res.wc); return 0; }
\ No newline at end of file |