else if (
else
Операции "послать в стек" и "взять из стека" сами по себе тривиальны, однако по мере добавления к ним механизмов обнаружения и нейтрализации ошибок становятся достаточно длинными. Поэтому их лучше оформить в виде отдельных функций, чем повторять соответствующий код по всей программе. И конечно необходимо иметь отдельную функцию для получения очередного оператора или операнда.
Главный вопрос, который мы еще не рассмотрели, - это вопрос о том, где расположить стек и каким функциям разрешить к нему прямой доступ. Стек можно расположить в функции
Переход от эскиза к программе достаточно легок. Если теперь программу представить как текст, расположенный в одном исходном файле, она будет иметь следующий вид:
#include /* могут быть в любом количестве */
#define /* могут быть в любом количестве */
main() {…}
void push (double f) {…}
double pop (void) {…}
int getop(char s[]) {…}
Позже мы обсудим, как текст этой программы можно разбить на два или большее число файлов.
Функция
#include ‹stdio.h›
#include ‹stdlib.h› /* для atof() */
#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 '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
pop2 = pop();
if (op2 != 0.0)
push(pop() / op2);
else
printf("ошибка: деление на нуль\n");
break;
case '\n':
printf("\t%.8g\n", pop());
break;
default:
printf("ошибка: неизвестная операция %s\n", s);
break;
}
}
return 0;
}
Так как операторы + и * коммутативны, порядок, в котором операнды берутся из стека, не важен, однако в случае операторов - и /, левый и правый операнды должны различаться. Так, в
push(pop() - pop()); /* НЕПРАВИЛЬНО */
очередность обращения к
#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");