summaryrefslogtreecommitdiff
path: root/ex1-10.c
diff options
context:
space:
mode:
Diffstat (limited to 'ex1-10.c')
-rw-r--r--ex1-10.c66
1 files changed, 49 insertions, 17 deletions
diff --git a/ex1-10.c b/ex1-10.c
index 0b0c018..f17e748 100644
--- a/ex1-10.c
+++ b/ex1-10.c
@@ -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