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.