summaryrefslogtreecommitdiff
path: root/ex5-1.c
blob: 9a43c0020485db7d6ce24699630321440ad1b063 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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