Exercise 4.11 - getline using static

Question

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

/**
 * modify getop so that it does not need to use ungetch: Hint: static int lastc
 **/

#include<stdio.h>
#include<stdlib.h>

#define MAXOP 100
#define NUMBER '0'

int getop(char []);

void push(double);

double pop(void);

/* reverse polish calculator */

int main(void) {
    int type;
    double op2;
    char s[MAXOP];

    while ((type = getop(s)) != EOF) {
        switch (type) {
            case NUMBER:
                push(atof(s));
                break;
            case '+':
                push(pop() + pop());
                break;
            case '*':
                push(pop() * pop());
                break;
            case '-':
                op2 = pop();
                push(pop() - op2);
                break;
            case '/':
                op2 = pop();
                if (op2 != 0.0)
                    push(pop() / op2);
                break;
            case '\n':
                printf("\t%.8g\n", pop());
                break;
            default:
                printf("error: unknown command %s\n", s);
                break;
        }
    }
    return 0;
}


#define MAXVAL 100

int sp = 0;
double val[MAXVAL];

/* push : push f onto value stack */

void push(double f) {
    if (sp < MAXVAL)
        val[sp++] = f;
    else
        printf("error: stack full,can't push %g\n", f);
}

/* pop: pop and return top value from stack */

double pop(void) {
    if (sp > 0)
        return val[--sp];
    else {
        printf("error: stack empty\n");
        return 0.0;
    }
}

#include<ctype.h>

int getch(void);

/* getop: get next operator or numeric operand */

int getop(char s[]) {
    int c, i;
    static int lastc = 0;

    if (lastc == 0)
        c = getch();
    else {
        c = lastc;
        lastc = 0;
    }

    while ((s[0] = c) == ' ' || c == '\t')
        c = getch();

    s[1] = '\0';

    if (!isdigit(c) && c != '.')
        return c;

    i = 0;
    if (isdigit(c))
        while (isdigit(s[++i] = c = getch()));
    if (c == '.')
        while (isdigit(s[++i] = c = getch()));
    s[i] = '\0';

    if (c != EOF)
        lastc = c;

    return NUMBER;
}

#define BUFSIZE 100

char buf[BUFSIZE];
int bufp;

int getch(void) {
    return (bufp > 0) ? buf[--bufp] : getchar();
}

Explanation

The point of illustration of this program is the static variable, lastc, which gets initialized once as a static variable and maintains its state at each invocation. The getop function declares the variable lastc and proceeds as before. It calles getch to get the last character and if it is a EOF it returns the EOF, if it a space ignores and if not a number, it returns immediately and ensures that it parses a valid number.

At the end, it verifies that the character read is not EOF and the stores the last character which was read using getch in the lastc variable.

int getop(char s[])
{
        int c,i;
        static int lastc = 0;

        if(lastc == 0)
                c = getch();
        else
        {
                c = lastc;
                lastc = 0;
        }

        while((s[0]=c) == ' ' || c == '\t')
                c = getch();

        s[1]='\0';

        if(!isdigit(c) && c!= '.')
                return c;

        i = 0;

        if(isdigit(c))
                while(isdigit(s[++i] =c=getch()))
                        ;

        if(c=='.')
                while(isdigit(s[++i] =c=getch()))
                        ;
        s[i]='\0';

        if(c!=EOF)
                lastc=c;

        return NUMBER;
}

The program execution looks like this.

10 10 +
        20
201 305 + 20 *
        10120

Visualize It

Try It