#include #include /* для atof() */ #define MAXOP 100 /* макс. размер операнда или оператора */ #define NUMBER '0' /* признак числа */ int getop (char []); void push (double); double pop (void); double tail (void); void duplicate(void); void printstack(void); void swap(void); void clear(void); /* калькулятор с обратной польской записью */ int main() { int type; double op1, 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("ошибка: деление на нуль\n"); break; case '%': op2 = pop(); if (op2 != 0.0) { op1 = pop(); if (op1 > op2) push ( op1 - op2 * (int) (op1 / op2) ); else push (0.0); } else printf("ошибка: деление на нуль\n"); break; case 't': printf("\n\t%.8g\n", tail()); break; case 'd': duplicate(); break; case 'p': printstack(); break; case 's': swap(); break; case 'c': clear(); break; case '\n': printf("\t%.8g\n", pop()); break; default: printf("ошибка: неизвестная операция %s\n", s); break; } } return 0; } #define MAXVAL 100 /* максимальная глубина стека */ int sp = 0; /* следующая свободная позиция в стеке */ double val[MAXVAL]; /* стек */ /* push: положить значение f в стек */ void push(double f) { if (sp < MAXVAL) val[sp++] = f; else printf("ошибка: стек полон, %g не помещается\n", f); } /* pop: взять с вершины стека и выдать в качестве результата */ double pop(void) { if (sp > 0) return val[--sp]; else { printf ("ошибка: стек пуст\n"); return 0.0; } } /* tail: взять с вершины стека и выдать в качестве результата */ double tail(void) { if (sp > 0) return val[sp-1]; else { printf ("ошибка: стек пуст\n"); return 0.0; } } /* duplicate: дублировать элемент с вершины стека */ void duplicate(void) { if (sp > 0) { val[sp] = val[sp-1]; ++sp; } else { printf ("ошибка: стек пуст\n"); } } /* printstack: печать содержимого стека */ void printstack(void) { int i; printf ("\n"); if (sp > 0) { for (i = 0; i < sp; ++i) printf ("%.8g ", val[i]); } else { printf ("ошибка: стек пуст\n"); } } /* swap: обмен содержимым двух верхних ячеек стека */ void swap(void) { double t; if (sp > 1) { t = val[sp-2]; val[sp-2] = val[sp-1]; val[sp-1] = t; } else { printf ("ошибка: недостаточно элементов для обмена\n"); } } /* clear: очистка содержимого стека */ void clear(void) { sp = 0; } #include int getch(void); void ungetch(int); /* getop: получает следующий оператор или операнд */ int getop(char s[]) { int i=0, c, t; while ((s[i] = c = getch()) == ' ' || c == '\t'); if (!isdigit(c) && c != '.'){ if (c == '-') { if (isdigit(t = getch()) || t == '.') { c = t; s[++i] = c; } else { ungetch(t); return c; /* не число */ } } else { return c; /* не число */ } } if (isdigit(c)) /* накапливаем целую часть */ while (isdigit(s[++i] = c = getch())); if (c =='.') /* накапливаем дробную часть */ while (isdigit(s[++i] = c = getch())); s[i] = '\0'; if (c != EOF) ungetch(c); return NUMBER; } #define BUFSIZE 100 char buf[BUFSIZE]; /* буфер для ungetch */ int bufp = 0; /* след. свободная позиция в буфере */ int getch(void) /* взять (возможно возвращенный) символ */ { return (bufp > 0) ? buf[--bufp] : getchar(); } void ungetch(int c) /* вернуть символ на ввод */ { if (bufp >= BUFSIZE) printf("ungetch: слишком много символов\n"); else buf[bufp++] = c; }