Exercise 4-11

Modify getop so that it doesn't need to use ungetch. Hint: use an internal static variable.

Similar to before, we will use the code from exercise 4-3 as a starting point as implementing this in our more recent programs would break functionality.

In order to rewrite getop without having the ability to push back a character, we change c to be static, which means its value carries over the next time getop is called. At the start of getop, instead of always reading in at least one new character, we only read in characters as long as c is a whitespace character. c will be initialized to a whitespace character so that on the first run, the next character is read. Doing this instead means we no longer need to push back c as it will carry over by default. In cases where we would normally not execute ungetch, we simply set c to whitespace so that the next character will be read into c the next time getop is called. Note that as c is actually equal the character that will carry over, wherever we returned c before, we now need to return s[0] instead (which prior to this change was equivalent to c.)

    /* getop:  get next operator or numeric operand */
    int getop(char s[])
    {
        int i, c;
        int i;
        static int c = ' ';
    
        while ((s[0] = c = getch()) == ' ' || c == '\t')
            ;
        while (c == ' ' || c == '\t')
            s[0] = c = getchar();
        s[1] = '\0';
        if (!isdigit(c) && c != '.' && c != '+' && c != '-') {
            c = ' ';        /* read next character next time getop is run */
            return c;       /* not a number */
            return s[0];    /* not a number */
        }
        i = 0;
        if (isdigit(c) || c == '+' || c == '-') /* collect integer part */
            while (isdigit(s[++i] = c = getchar()))
                ;
        if (c == '.')   /* collect fraction part */
            while (isdigit(s[++i] = c = getchar()))
                ;
        if (c != EOF)
            ungetch(c);
        s[i] = '\0';
        if ((s[0] == '+' || s[0] == '-') && i == 1)
            return s[0];    /* return operator if no digits afterwards */
        return NUMBER;
    }