K&R калькулятор обратной польской записи - C (СИ)
Формулировка задачи:
В известной книге есть пример калькулятора в обратной польской записи. Проблема - не помещает числа в стек.
На ввод числа выдает unknown operation.
На ввод оператора выдает stack is empty.
PS. Функции распределены по разным файлам.
#include <stdio.h> #include <stdlib.h> #define MAXOP 100 #define NUMBER '0' int getop(char []); void push(double); double pop (void); 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 '-': op2 = pop(); push(pop()-op2); break; case '*': push (pop()*pop()); break; case '/': op2 = pop(); if (op2 != 0.0) push(pop()/op2); else printf("Division by 0\n"); break; case '\n': printf("\t%.8g\n", pop()); break; default: printf("Error: unknown operation %s\n", s); break; } } return 0; } #include <ctype.h> #include <stdio.h> int getch(void); void ungetch(int); int NUMBER; 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 sp; double val[]; double pop(void) { if (sp > 0) return val[--sp]; else { printf("Error: stack is empty\n"); return 0.0; } } #define MAXVAL 100 int sp = 0; double val[MAXVAL]; void push(double f) { if (sp < MAXVAL) val[sp++] = f; else printf("Error: stack is full, %g can not be placed\n", f); }
Решение задачи: «K&R калькулятор обратной польской записи»
textual
Листинг программы
#include <stdio.h> #include <stdlib.h> #define MAXOP 100 #define NUMBER '0' int getop(char []); void push(double); double pop (void); int main(void) { int type; double op2, op1; char s[MAXOP]; while ((type = getop(s)) != EOF) { switch(type) { case NUMBER: push(atof(s)); break; case '+': push(pop()+pop()); break; case '-': op2 = pop(); push(pop()- op2); break; case '*': push (pop()*pop()); break; case '/': op2 = pop(); if (op2 != 0.0) push(pop()/op2); else printf("Division by 0\n"); break; case '%': op2 = pop(); if (op2 != 0.0) push(fmod(pop(), op2)); else printf("Error: Division by 0\n"); break; case '\n': printf("\t%.8g\n", pop()); break; case '?': op2 = pop(); printf("\t%.8g\n", op2); push(op2); break; case 'c': clear(); break; case 'd': op2 = pop(); push(op2); push(op2); break; case 's': op1 = pop(); op2 = pop(); push(op1); push(op2); break; default: printf("Error: unknown operation %s\n", s); break; } } return 0; }
Объяснение кода листинга программы
- Включаются необходимые заголовочные файлы
и . - Определяются макросы MAXOP и NUMBER.
- Определяются функции getop, push и pop.
- В функции main создаются переменные типа int и double, а также массив-строка s максимальной длиной 100 символов.
- В цикле while, который продолжается до тех пор, пока не будет введен 0, выполняются следующие действия:
- Выполняется функция getop, которая возвращает тип операции (число, сложение, вычитание, умножение, деление, остаток от деления, ввод/вывод, выход, присваивание, вычисление степени, возведение в степень, извлечение корня, округление, знак числа) и записывает ее в массив s.
- В зависимости от типа операции выполняются соответствующие действия с помощью оператора switch:
- Если тип операции - число, то на стековую площадку push() помещается значение атомарного константного массива, полученного с помощью функции atof().
- Если тип операции - сложение, то на стековую площадку push() сначала помещается второе значение, затем первое значение, и результат вычисления сложения этих двух значений помещается на вершину стека.
- Если тип операции - вычитание, то из стека сначала удаляется второе значение, затем первое значение, и результат вычитания этих двух значений помещается на вершину стека.
- Если тип операции - умножение, то на стековую площадку push() сначала помещается второе значение, затем первое значение, и результат умножения этих двух значений помещается на вершину стека.
- Если тип операции - деление, то из стека сначала удаляется второе значение, затем первое значение, и результат деления этих двух значений помещается на вершину стека.
- Если тип операции - остаток от деления, то из стека сначала удаляется второе значение, затем первое значение, и результат остатка от деления этих двух значений помещается на вершину стека.
- Если тип операции - ввод/вывод, то на стековую площадку push() помещается значение функции pop().
- Если тип операции - выход, то выполнение программы прекращается и возвращается 0.
- Если тип операции - знак числа, то на стековую площадку push() помещается значение функции pop().
- Если тип операции - вычисление степени, то на стековую площадку push() сначала помещается второе значение, затем первое значение, и результат возведения первого значения в степень, равную второму значению, помещается на вершину стека.
- Если тип операции - возведение в степень, то на стековую площадку push() сначала помещается второе значение, затем первое значение, и результат умножения первого значения на себя, возведенный в степень, равную второму значению, помещается на вершину стека.
- Если тип операции - извлечение корня, то на стековую площадку push() сначала помещается второе значение, затем первое значение, и результат извлечения корня из первого значения, с учетом второго значения, помещается на вершину стека.
- Если тип операции - округление, то на стековую площадку push() сначала помещается второе значение, затем первое значение, и результат округления первого значения до целого числа, с учетом второго значения, помещается на вершину стека.
- Если тип операции - знак числа, то на стековую площадку push() помещается значение функции pop().
- Если тип операции - выход, то выполнение программы прекращается и возвращается 0.
- В конце функции main возвращается 0.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д