Головоломка на второй стек в постфиксном калькуляторе - PullRequest
0 голосов
/ 27 апреля 2019

Я недавно читаю «TCPL». В разделе 4.3 существует классический случай «постфиксный калькулятор».У меня есть вопрос по делу: см. Код дела (копия из книги):

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

#define MAXOP 100
#define NUMBER '0'
#define MAXVAL 100 /* maxmium depth of val stack */
#define BUFFSIZE 100


int sp = 0;
double val[MAXVAL];

int bufp = 0; /* next free size in buf*/
char buf[BUFFSIZE]; /* buffer in ungetch */


int getch(void);
void ungetch(int);
int getop(char []);
void push(double);
double pop(void);

int main()
{
    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);
                }
                else
                {
                    printf("error: zero divisor. \n");
                }
                break;
            default:
                printf("\t%.8g\n", pop());
                break;
        }
    }
    return 0;
}


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


/* pop: pop and return value on the top of the stack */
double pop(void)
{
    if (sp > 0) {
        return val[--sp]; 
    }
    else {
        printf("error: stack empty.\n");
        return 0.0;
    }
}



/* getop: get next character or numeric operand */
int getop(char s[])
{
    int i, c;

    while ((s[0] = c = getch()) == ' ' || c == '\t') {
        ;
    }
    s[1] = '\0';
    if (!isdigit(c) && c != '.' ) { /* operator */
        return c;
    }
    i = 0;
    if (isdigit(c)) {               /* collect integer part */
        while (isdigit(s[++i] = c = getch())) {
            ;
        }
    }
    if (c == '.') {                 /* collect fraction part */
        while (isdigit(s[++i] = c = getch())) {
            ;
        }
    }
    s[i] = '\0';
    if (c != EOF) {
        ungetch(c);
    }
    return NUMBER;
}


/* getch:  get a (possibly pushed-back) character */
int getch(void)
{
    return (bufp > 0)? buf[--bufp] : getchar();
}


/* ungetch: push character back on input */
void ungetch(int c)
{
    if (bufp >= BUFFSIZE) {
        printf("ungetch: too many characters in buufer.\n");
    }
    else {
        buf[bufp++] = c;
    }
}

Существует глобальный массив символов buf, это как стек, а две последние функции предназначены для'pop' и 'push' на buf.

Мой вопрос: в каком случае стек buf содержит более одного элемента?

Единственный шанс, что ungetch() может быть вызван, - это функция getop(), однако в getop() функция getch() вызывается как минимум один раз.

1 Ответ

0 голосов
/ 27 апреля 2019

Мой вопрос: в каком случае в стеке buf содержится более одного элемента?

никогда, buf может быть просто символом, он используется только для запоминания символа, размещенного сразу после числа, чтобы не потерять его

Код можно изменить, чтобы он не использовался:

/* getch:  get a (possibly pushed-back) character */
int getch(void)
{
    return getchar();
}


/* ungetch: push character back on input */
void ungetch(int c)
{
  ungetc(c, stdin);
}

Компиляция и исполнение:

pi@raspberrypi:/tmp $ gcc pf.c
pi@raspberrypi:/tmp $ ./a.out
1 2 3 4 + + +
    10

Или используя тот факт, что можно сохранить только один символ:

int SavedChar = EOF;

/* getch:  get a (possibly pushed-back) character */
int getch(void)
{
  if (SavedChar == EOF)
    return getchar();

  int r = SavedChar;

  SavedChar = EOF;

  return r;
}

/* ungetch: push character back on input */
void ungetch(int c)
{
  SavedChar = c;
}

Компиляция и исполнение:

pi@raspberrypi:/tmp $ gcc pf.c
pi@raspberrypi:/tmp $ ./a.out
1 2 3 4 + + +
    10
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...