Таким образом, программа состоит из цикла, обрабатывающего на каждом своем шаге очередной встречаемый оператор или операнд:
while (следующий элемент не конец-файла)
if (число)
послать его в стек
else if (оператор)
взять из стека операнды
выполнить операцию
результат послать в стек
else if (новая-строка)
взять с вершины стека число и напечатать
else
ошибка
Операции "послать в стек" и "взять из стека" сами по себе тривиальны, однако по мере добавления к ним механизмов обнаружения и нейтрализации ошибок становятся достаточно длинными. Поэтому их лучше оформить в виде отдельных функций, чем повторять соответствующий код по всей программе. И конечно необходимо иметь отдельную функцию для получения очередного оператора или операнда.
Главный вопрос, который мы еще не рассмотрели, - это вопрос о том, где расположить стек и каким функциям разрешить к нему прямой доступ. Стек можно расположить в функции main и передавать сам стек и текущую позицию в нем в качестве аргументов функциям push ("послать в стек") и pop ("взять из стека"). Но функции main нет дела до переменных, относящихся к стеку, - ей нужны только операции по помещению чисел в стек и извлечению их оттуда. Поэтому мы решили стек и связанную с ним информацию хранить во внешних переменных, доступных для функций push и pop, но не доступных для main.
Переход от эскиза к программе достаточно легок. Если теперь программу представить как текст, расположенный в одном исходном файле, она будет иметь следующий вид:
>#include /* могут быть в любом количестве */
>#define /* могут быть в любом количестве */
>объявления функций для main
>main() {…}
>внешние переменные для push и pop
>void push (double f) {…}
>double pop (void) {…}
>int getop(char s[]) {…}
>подпрограммы, вызываемые функцией getop
Позже мы обсудим, как текст этой программы можно разбить на два или большее число файлов.
Функция main - это цикл, содержащий большой переключатель switch, передающий управление на ту или иную ветвь в зависимости от типа оператора или операнда. Здесь представлен более типичный случай применения переключателя switch по сравнению с рассмотренным в параграфе 3.4.
>#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;