Диалекты бейсика для ZX Spectrum 1992 г.

Megabasic - Структурное программирование.


СТРУКТУРНОЕ ПРОГРАММИРОВАНИЕ_

ENDPROC, BRANCH, MTASK, PCLEAR, REPEAT, UNTIL, POP, PUSH, RESTART, BROFF, BRON

Название этого раздела — «Структурное программирование», несколько условно, поскольку его рамки шире. Здесь собраны все средства MegaBasic, так или иначе служащие для придания программам внутреннего совершенства (впрочем, не всегда явно обнаруживаемого в процессе их выполнения).

Как почти все диалекты Бейсика для ZX Spectrum, MegaBasic располагает инструментом процедур (см. также стр. 176, 260). Правда, это не совсем «честные» процедуры, поскольку параметры их не являются локальными. Из этого следует, что использование одних и тех же переменных в процедуре и в основной программе может привести к недоразумениям.

Для оформления какого-либо блока программы в виде процедуры необходимо задать ее начало (заголовок) и конец. Это делается посредством двух операторов:

@<имя программы>_[<список формальных параметров>] в начале процедуры76 и

ЕНОРРОС_<имя процедуры>

в конце.

Имя процедуры в операторе ENDPROC в случаях, исключающих двусмысленность, может опускаться.

В заголовке процедуры после символа подчеркивания приводится перечень формальных параметров, с которыми надлежит работать процедуре. Ими могут быть числовые и строковые переменные.

Вызов процедуры может осуществляться только из основной программы77 указанием имени процедуры и, через символ подчеркивания, списка фактических параметров, то есть значений всех переменных, упомянутых в заголовке процедуры:

<имя процедуры>_<список фактических параметров>

Фактические параметры могут быть только конкретными значениями (не переменными).

Имя процедуры может иметь произвольную длину и состоять из любых символов (кроме псевдографики, UDG и пробелов), но начинаться должно обязательно с буквы. Длина имени ограничена лишь представлениями программиста об удобстве. В качестве имен процедур нельзя использовать ключевые слова MegaBasic и Spectrum-Бейеика.

Приведем пример использования процедур: 5 CLS

10 Z_5,RND*t6lRNDH2,52lt,12,5<1.l"nePBbiM прогон": REM Вызов процедуры

30 Z__6,RND*16,RND*20,44,2,14,6,2."Second run" 40 GO TO 10

1000 @Z_WfC,L,G,F,SfPP,ll,A$: REM Заголовок процедуры 1010 CURRENT_W:WINDOW_C,L,8,G:MODE_4:FONT_F:STIPPLE_S 1020 BRIGHT 1: PAPER PP: INK ll:CLW_W,0 1040 PRINT A$: PAUSE 40 1050 SCROLL_1 ,—64

1100 ENDPROC: REM Конец процедуры

Здесь процедура Z имеет 9 параметров и выполняется циклически, причем два параметра, определяющие положение окна, каждый раз меняют свои значения случайным образом.

Новые возможности в оперировании подпрограммами открывают два схожих по действию оператора BRANCH и MTASK.

Оператор

BRANCH_n

после каждой следующей за ним строки программы навязывает выполнение подпрограммы, расположенной со строки с номером п. Выглядит это так, как будто к каждой строке программы довесили через двоеточие оператор GO SUB п. Только подпрограмма, на которую ссылается BRANCH, должна завершаться оператором ENDPROC (без имени процедуры), а не RETURN Прекращается это построчное «прыгание» после появления в программе оператора BRANCH„0. Использование оператора BRANCH проиллюстрировано в программе, которая рассчитывает длину магнитной ленты, необходимую для заданного времени записи:

20 CLS

200 CURRENT_6:WINDOW_4,0,8,30: PAPER 5: INK 1 :CLW_0 205 FONT_1 :MODE_2

210 PRINT INK 1;"ВРЕМЯ.....ВОСПРОИЗВЕДЕНИЯ": MODE_3

215 CURRENT_7:WINDOW_4,34,8,30: PAPER 6:CLW_0

220 FONT_1:MODE_2: PRINT INK 4;"ДЯИНА ЛЕНТЫ":МООЕ_3

230 BRANCH_400: INPUT "МИНУТ ";М;"СЕКУНД";5: LET A$=STR$

M+" ' "+STR$ S+" " " ":CURRENT_6 240 LET T=M*60+S: LET L=T*.1905: LET A$=STR$ INT

L+" m":CURRENT_7: GO TO 230 400 PRINT AT 3,8; INK 2;A$; 410 ENDPROC

Оператор

MTASK__n

после каждой строки основной программы отсылает компьютер к подпрограмме (начало подпрограммы задается параметром п). Но при каждой отсылке выполняется не вся подпрограмма, а лишь одна очередная ее строка. Получается эффект параллельного выполнения двух программ (основной и подпрограммы): строка из программы — строка из подпрограммы, и так до появления оператора MTASK_0.

Операторы BRANCH и MTASK являются взаимоисключающими, иначе говоря, не могут работать одновременно. Причем MTASK имеет более высокий приоритет, то есть работать будет именно он при попытке одновременного запуска обоих операторов.

В сочетании с процедурами бывает необходимо использовать еще один оператор:

PCLEAR

Для того чтобы объяснить его назначение, нужно сначала сказать о внутреннем стеке MegaBasic. Стек обслуживает ветвление программ средствами MegaBasic: при входе в процедуры, при выполнении операторов BRANCH и MTASK, а также при выполнении цикла REPEAT...UNTIL (о нем — дальше). В стеке запоминаются номер строки и номер оператора в ней, к выполнению которого нужно вернуться после завершения процедуры, подпрограммы или цикла. После возврата по стеку адрес возврата (значения номеров строки и оператора) снимается с него (стирается). Всего в стек помещается до 1 0 адресов возврата, и, следовательно, имеется возможность использовать до 10 вложенных процедур или циклов. Если программа структурирована нечетко, возможен останов ее с выдачей сообщений о переполнении стека PROC stack overflow или о его опустошении — PROC stack underflow. Как раз для того, чтобы избежать переполнения стека, и нужен оператор PCLEAR (без параметров), выполняющий его очистку.

Теперь обещанный рассказ о цикле REPEAT...UNTIL. Начало цикла задает оператор

REPEAT

- который используется без параметров. Оператор

UNTIL_r

ограничивает цикл снизу и определяет условие его завершения. Таким образом, выход из цикла происходит, когда значение параметра г становится ненулевым. После этого выполнение программы продолжается со следующей после UNTII__г строки. Оператор

UNTIL удобно использовать совместно с логическими операторами, что и показано в примере программы, которая экспериментирует с различными, в том числе и неразрешенными размерами окон:

10 CURRENT_6:WINDOW_0,36,12,28: PAPER 5: INK 1 :MODE_6,4:

STIPPLE_12:FONT_1: PCLEAR 20 REPEAT

30 LET n=INT (RND*23): LET c=INT (RND*63): LET h=INT (RND*10):

LET g=INT (RND*40) 40 PAUSE 30

50 LET f=(n+h)>23: LET w=(c+g)>63: LET w=h>1: LET s=g>1 60 IF f OR w THEN POP: PUSH_1,100: LET w=0

70 UNTII__w AND s

80 CLW_6lO:CURRENT_5:WINDOW_n.c,hlg: PAPER RND*7: INK 9:MODE_1 :CLW_5,0: PRINT "НОРМА!"

90 RUN

100 PRINT "ОКНО" r "СЛИШКОМ БОЛЬШОЕ":RUN

MegaBasic позволяет при выполнении оператора UNTIL осуществлять переход не только на начало цикла, но и в любое другое место программы (этот прием использован в примере). Для этого надо снять с вершины стека адрес перехода, записанный туда оператором REPEAT, и занести в стек требуемые номера строки и оператора в ней. Очистку вершины стека выполняет «беспарамет-ровый» оператор

POP

А занесение в стек нового адреса возврата — оператор

PUSH_s,n

В нем параметр п задает номер строки, s — номер оператора в ней, куда должен быть осуществлен переход.

Отметим, что в случае «нормального» выхода из цикла, то есть при выполнении условия, записанного в UNTIL, управление будет передано следующему «а UNTIL оператору, независимо от адреса перехода, занесенного в стек оператором PUSH.

В MegaBasic имеется оператор

RESTART_n

- который при сбое программы вместо выдачи сообщения об ошибке отсылает компьютер к строке с номером п. К сожалению, RESTART реагирует предусмотренным образом только на ошибки, характерные для Spectrum-Бейсика, а при ошибках выполнения операторов MegaBasic по-прежнему выдает сообщения. Тем не менее, с учетом этого ограничения, RESTART вполне можно использовать, например, для возврата из любого места программы в главное меню по нажатию клавиши Break, которое приравнивается Spectrum-Бейсиком к ошибке.

Применение оператора RESTART проиллюстрировано примером, где в строку 20 умышленно введена возможность периодического возникновения ошибки (недопустимое значение параметра в операторе PAPER):

10 RESTART_1 OOOiBROFF

20 CURRENT_6: PAPER RND* 10: BRIGHT 1: INK 9

30 CLS : PAUSE 30

40 GO TO 20 1000 FONT_1:MODE_4:STIPPLE_12 1010 PRINT AT 10,20;"ОШИБКА!" 1020 PAUSE 100: GO TO 20

225

8 Зак. № 192

Отмена действия оператора RESTART осуществляется в форме RESTART_OFF. Кстати, в этом примере использован также оператор противоположного свойства

BROFF

Он предотвращает реакцию на клавишу Break. В пример он включен для того, чтобы сообщение в центре экрана появлялось только в результате ошибки, а не нажатия Break. Действие оператора BROFF отменяется оператором

BRON

Иногда рекомендуют использовать оператор BROFF для защиты программ на MegaBasic от несанкционированного доступа. Если учесть, что команды ESCAPE и RESTART, о которых мы говорили в начале главы, исправно действуют и при отключении клавиши Break, то от тех любопытных, кто знаком с MegaBasic, такая защита более чем иллюзорна. От тех же, чьи познания ограничены Spectrum-Бейсиком, лучшей защитой будет сам текст программы, написанный на MegaBasic.




СОДЕРЖАНИЕ:
  1. Laser Basic - Вывод спрайтов на экран; Вывод на экран части спрайта; Перенос атрибутов; Преобразование окна экрана; Наборы переменных; Перемещение спрайтов; Наложение спрайтов; Копирование изображения с экрана в спрайт; Преобразование спрайтов; Скроллинг пейзажа; Изменение размеров области спрайт-файла; Вспомогательные графические операторы и функции; Определение столкновений спрайтов; Сервисные операторы и функции; Процедуры; Загрузка и запись программ.


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Новость недели - я наконец-то достал демки с FT'98.
Обзор софта - О новинках ПО: E-Swat, Fiendish Freddy'S, Gun RunnerR, Margo, Ruggsy Ranger,Battle of the Planet, Transmuter, Super Text Utility v1.3, ZX-Winword v2.1, Turbo Disk Utility v1.0, Fast Disk Copier v2.0, X-Player v7.9 , PCD v6.2.
Обратная связь - контакты редакции.
Обратная связь - контакты редакции.
Вступление - содержание номера.

В этот день...   28 марта