diff options
author | Martin Ashby <martin@ashbysoft.com> | 2023-02-07 22:20:47 +0000 |
---|---|---|
committer | Martin Ashby <martin@ashbysoft.com> | 2023-02-07 22:20:47 +0000 |
commit | cabe1a14b31edce1a247c367f8e1d7265abec34e (patch) | |
tree | e66fd91f6682d084ea8484b1be43bd5631dc7610 /ex5-1.c | |
parent | 7fa502ba4e60ce762ab529996c66a1a831cb789f (diff) | |
download | learn-c-cabe1a14b31edce1a247c367f8e1d7265abec34e.tar.gz learn-c-cabe1a14b31edce1a247c367f8e1d7265abec34e.tar.bz2 learn-c-cabe1a14b31edce1a247c367f8e1d7265abec34e.tar.xz learn-c-cabe1a14b31edce1a247c367f8e1d7265abec34e.zip |
Chapter 5
Diffstat (limited to 'ex5-1.c')
-rw-r--r-- | ex5-1.c | 97 |
1 files changed, 97 insertions, 0 deletions
@@ -0,0 +1,97 @@ +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> + +#define PUSHBACK_MAX 10 +typedef struct { + FILE* stream; + int pushback[PUSHBACK_MAX]; + int pushback_ix; +} StreamWithPushback; + +StreamWithPushback swpb_new(FILE* f) { + StreamWithPushback ret; + ret.stream = f; + ret.pushback_ix = 0; + for (int i=0; i<PUSHBACK_MAX; i++) { + ret.pushback[i] = -1; + } + return ret; +} + +int getch(StreamWithPushback* swpb) { + if (swpb->pushback_ix > 0) { + int ch = swpb->pushback[swpb->pushback_ix]; + swpb->pushback_ix--; + return ch; + } + return getc(swpb->stream); +} + +void ungetch(StreamWithPushback* swpb, int ch) { + if (swpb->pushback_ix >= PUSHBACK_MAX) { + fprintf(stderr, "pushback buffer was full!\n"); + exit(1); + } + swpb->pushback[swpb->pushback_ix] = ch; + swpb->pushback_ix++; +} + +/* getint: get next integer from input into *pn */ +int getint(StreamWithPushback* swpb, int *pn) { + int c, sign; + + while (isspace(c = getch(swpb))) {} + + if (!isdigit(c) && c != EOF && c != '+' && c != '-') { + ungetch(swpb, c); + return 0; + } + + sign = (c == '-') ? -1 : 1; + if (c == '+' || c == '-') { + c = getch(swpb); + // If c isn't then a digit, then we don't have a number. + if (!isdigit(c)) { + ungetch(swpb, c); + // Push the sign character back as well, don't consume it + ungetch(swpb, sign == -1 ? '-' : '+'); + return 0; + } + } + + for (*pn = 0; isdigit(c); c = getch(swpb)) { + *pn = 10 * *pn + (c - '0'); + } + *pn *= sign; + + if (c != EOF) { + ungetch(swpb, c); + } + return c; +} + +#ifndef test + +int main(void) { + int p, x; + StreamWithPushback swpb = swpb_new(stdin); + while ((x = getint(&swpb, &p)) != EOF) { + if (x > 0) { + printf("%d\n", p); + } else { + printf("not a number!\n"); + } + } +} + +#else + +#include "CuTest.h" + +// I could write unit tests here, using fmemopen +// instead of reading something off the filesystem. + +// But I can't be bothered. + +#endif
\ No newline at end of file |