Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Таунсенд Проектирование и программная реализац...doc
Скачиваний:
15
Добавлен:
12.11.2019
Размер:
4.53 Mб
Скачать

If a then или if a else в then

Оператор IF выполняет ветвление программы и производит над стеком действие (f => ). Если снятый с вершины стека приз- нак (флаг) является истинным, то после оператора IF выполняется группа команд А, в противном случае начинает выполняться груп- па команд В, стоящая за оператором ELSE (или следующий за IF оператор, если ветвь ELSE отсутствует). После завершения выпол- нения группы команд В управление передается оператору, стояще- му за оператором THEN.

В конструкции цикла BEGIN-UNTIL (рис. 6.4c) значение флага проверяется после каждого выполнения группы команд А. Слово UNTIL, как и слово IF, снимает значение флага с вершины стека и производит проверку его истинности. Если этим значением является ложь, то группа команд А повторяется. Другими словами, выполняются те же действия, что и в конструкции ELSE оператора ветвления IF при ложном значении флага.

На рис. 6.4D представлена схема цикла WHILE. Повторное выполнение группы команд, находящихся внутри него, также про- исходит при значении флага ложь. Цикл BEGIN-WHILE начинает- ся с выполнения группы команд А, следующих за оператором BEGIN. Затем управление получает оператор WHILE, который снимает значение флага со стека; если флаг истинен, то выполня- ется группа команд В, которая завершается оператором REPEAT (повторить). Этот оператор передает управление обратно в начало цикла, т.е. оператору BEGIN. В терминах языка Форт эта конст- рукция записывается следующим образом:

BEGIN A WHILE В REPEAT

129

Рис.6.3. Пример неструктурированной программы. Циклы образуют перекрывающиеся куски программы, т.е. каждый цикл расположен частично внутри, частично снаружи другого цикла

130

Рис. 6.4. Управляющие конструкции языка Форт: (A)IF-THEN; (B)IF – ELSE THEN; (О BEGIN - UNTIL; (D) BEGIN - WHILE; (E)DO - LOOP или DO - +LOOP

131

В управляющих конструкциях IF, UNTIL, WHILE условием выполнения цикла является ложное значение флага. Поскольку действия этих операторов похожи друг на друга, то в их машинной реализации имеются общие подпрограммы периода выполнения. Если управляющее слово встречается в определении через двоето- чие (в период компиляции), то это приводит к компиляции фраг- мента, реализующего передачу управления в объектный код, кото- рый впоследствии будет выполняться при каждом обращении к этому слову. Детали реализации управляющих слов будут рассмот- рены позже при описании компилирующих слов.

В тех случаях, когда количество повторных шагов цикла изве- стно еще до начала его выполнения, полезной может оказаться та- кая конструкция, как цикл со счетчиком. В Бейсике такой опе- ратор имеет вид FOR - NEXT, а в Форте к этому типу относятся два оператора: DO - LOOP и DO - +LOOP. Их схемы приведены на рис. 6.4Е. Слово DO берет со стека два аргумента. Затем командой

DO ( граничное_значение счетчик_цикла ==> )

счетчик цикла и граничное значение помещаются в стек возврат? и удаляются из стека параметров. Счетчик цикла получает свое начальное значение, а граничное значение становится на единицу болы^е конечного значения счетчика цикла. В описании этого сло- ва упоминается название еще одного стека языка Форт -' стека воз- вратов. Он так называется потому, что используется в Форте в ос- новном для запоминания того места в программе, куда нужно вер- нуться после завершения встретившегося слова. Это действие вы- полняется виртуальной Форт-машиной, которая будет рассмотрена позже. Циклы типа DO также обращаются к этой машине, поско- льку все конструкции цикла должны находиться в границах од- ного (произвольного) слова Форта. DO-цикл использует стек воз- вратов только до тех пор, пока он находится внутри последола- тёльности команд, составляющих определение нового словя ..е. пока не встретится слово ; ).

Слово DO передает значения двух счетчиков из стека пара- метров в стек возвратов. Значением счетчика является начальная величина, передаваемая счетчику цикла, а граничное значение превосходит на единицу конечное значение. Это объясняется тем, что в цикле LOOP увеличение счетчика предшествует его сравне- нию с граничным значением. Если они оказываются равны, то вы- полнение цикла завершается. На каждом шаге цикла типа LOOP счетчик увеличивается на единицу.

Если требуется использовать шаг, отличный от единицы (при- чем это могут быть и отрицательные числовые значения), то следует обратиться к циклу иного типа, реализуемому словом +LO0P. В отличие от цикла LOOP, .который не взаимодействует со стеком параметров, +LOOP берет размер шага (т.е. величину, на которую увеличивается параметр цикла при каждом очередном вы-

132

полнении тела цикла) из этого стека. Чтобы иметь доступ к значе- нию счетчика в теле цикла, необходимо командой I предваритель- но занести его в стек параметров.

С помощью управляющих слов, которые мы ввели, можно по- строить примеры определения новых слов языка Форт. Так, для вывода на печать чисел от 1 до п следует прибегнуть к помощи цикла DO:

( п ==> )

: . #S 1+ 1 DO.I . LOOP ;

Считается хорошим стилем программирования помещать пе- ред определением слова его стековую нотацию. Это особенно умес- тно, если исходные тексты Форт-программы должны быть сохране- ны на дискете. Имя определяемого слова (в данном случае это #S) располагается непосредственно за двоеточием через пробел. Затем идет определение слова, состоящее из слов, с помощью которых числа будут отпечатаны.

Так как мы предполагаем, что числа передаются через стек, то слово +1 устанавливает граничное значение, превышающее пос- леднее выводимое на принтер число на единицу (поскольку пос- леднее число тоже должно быть отпечатано). Первым числом явля- ется единица, поэтому начальное значение счетчика цикла пола- гается равным единице. Это необходимо сделать до начала цикла DO, после чего стек будет содержать оба значения счетчика, кото- рые необходимы для выполнения цикла. Слово I, находящееся в теле цикла, помещает значение счетчика на стек, а команда . (то- чка) печатает его, одновременно удаляя со стека. Слово LOOP за- вершает цикл. Если ваш хомпьютер оснащен Форт-системой, по- пробуйте выполнить эту программу для п=10. При наборе команды

10 . #S

вы получите в качестве ответа следующую последовательность: 123456789 10 ok

Тот же самый результат может быть получен с помощью дру- гой управляющей конструкции, отличной от цикла DO. Так, в тер- минах цикла BEGIN-UNTIL упомянутая программа будет выгля- деть следующим образом:

( п ==> )

: . #S 1+ 1 BEGIN DU.P . 1+ 2DUP = UNTIL 2DROP ;

Определение слова, более длинное по сравнению с предыду- щим, свидетельствует о том, что в нашем случае лучше использо- вать цикл DO. В теле цикла на стек" помещаются два числа. Ко-

133

манда 2DUP делает копии значения счетчика и граничного значе- ния для выполнения команды = , которая их сравнивает, выраба- тывает значение флага и передает его команде UNTIL. При выхо- де из цикла эти значения все еще находятся на стеке, откуда их удаляет слово 2DROP. Чтобы представить последовательность дей- ствий, произведенных над стеком, следует аккуратно выписать его состояния под каждым словом - так будет виден результат их вы- полнения. Другие примеры использования управляющих слов мож- но увидеть на экранах с 40 по 45 и с 60 по 65, приведенных в гл. 7 и 9 соответственно, а также в приложении А.

Нестандартной, но весьма популярной управляющей констру- кцией является слово CASE, включающее в свою очередь слова OF, ENDOF и ENDCASE. Это слово служит обобщением конструк- ции IF-THEN, поскольку допускает неограниченное количество ветвлений. Каждая ветвь заключается в символьные скобки OF и ENDOF. Приведем пример конструкции CASE:

( п ==> )

CASE