summaryrefslogtreecommitdiff
path: root/ex5-1.c
diff options
context:
space:
mode:
authorMartin Ashby <martin@ashbysoft.com>2023-02-07 22:20:47 +0000
committerMartin Ashby <martin@ashbysoft.com>2023-02-07 22:20:47 +0000
commitcabe1a14b31edce1a247c367f8e1d7265abec34e (patch)
treee66fd91f6682d084ea8484b1be43bd5631dc7610 /ex5-1.c
parent7fa502ba4e60ce762ab529996c66a1a831cb789f (diff)
downloadlearn-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.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/ex5-1.c b/ex5-1.c
new file mode 100644
index 0000000..9a43c00
--- /dev/null
+++ b/ex5-1.c
@@ -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