#include #include #include #define MAXOP 100 // Максимальный размер операдна (цифры) или оператора #define MAXVAL 100 // Максимальный размер стека (глубина) #define NUMBER '0' // Признак числа #define BUFSIZE 100 int getop(char[]); void push(double); double pop(void); int getch(void); void ungetch(int); int sp = 0; /* Следующая свободная позиция в стеке */ int bufp = 0; /* след, свободная позиция в буфере */ double val[MAXVAL]; /* stack */ char buf[BUFSIZE]; /* буфер для ungetch */ int getch(void) /* взять (возможно возвращенный) символ */ { return (bufp > 0) ? buf[--bufp] : getchar(); } void ungetch(int с) /* вернуть символ на ввод */ { if (bufp >= BUFSIZE) printf("ungetch: слишком много символов\n"); else buf[bufp++] = с; } void push(double f) { if (sp < MAXVAL) { val[++sp] = f; } else { printf("Stack maximum depth reached: %c", MAXVAL); } } double pop(void) { if (sp > 0) { return val[--sp]; } else { printf("Stack is empty. Returning 0.0"); return 0.0; } } /** * @brief Функция получения следующего оператора или операнда * * @param s массив символов для оценки */ int getop(char s[]) { int i, c; while ((s[0] = c = getch()) == ' ' || c == '\t') ; 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) ungetch(c); return NUMBER; } int main() { int type; double pop2; 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 '-': /* * Тут сначала извлекаем верхний операнд, из которого надо * вычитать. В отличии от `+`, `*` для `-` и `/` порядок операндов * важен. * * ---------- * - * 10 * 20 * ... * ---------- * * Чтобы сделать вычитание - надо из 20 вычесть 10 - получается * излекам со стека 10, затем 20 и делаем вычитание */ pop2 = pop(); push(pop() - pop2); break; case '/': /* * Тут примерно то-же самое, только еще надо сделать проверку * на ноль */ pop2 = pop(); if (pop2 != 0.0) push(pop() / pop2); else printf("Error: Division by zero\n"); break; case '\n': printf("\t%.g\n", pop()); break; default: printf("Error: Unknown operation %s\n", s); break; } } }