#include #include #include #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; ipushback_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