Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ZX-Review-1992-01-12.pdf
Скачиваний:
243
Добавлен:
28.03.2015
Размер:
2.43 Mб
Скачать

процедур, в большинстве случаев не позволяют использовать массивы в качестве параметров. БЕТА БЕЙСИК разрешает это, но правда, требует, чтобы они передавались только как ссылки. Они переименовываются вместо того, чтобы просто копироваться в область локальных переменных процедуры. Этим достигается экономия памяти, ведь компьютеру не надо одновременно хранить один массив два раза. Если же вам на самом деле нужна локальная копия Вашего массива для каких то временных манипуляций с ним, Вы можете внутри процедуры создать параллельный массив, объявив его как LOCAL, а затем скопировать в него содержание Вашего исходного массива, воспользовавшись для этого командой БЕТА БЕЙСИКа COPY, о чем мы еще скажем ниже, когда будем ее рассматривать вместе с командой JOIN. Вот демонстрационный пример, в котором показано, как можно найти сумму элементов массива.

300 DEF PROC total REF a(),REF sum

310 LOCAL n

320 LET sum=0

330 FOR n=1 TO LENGTH (1,"a()")

340 LET sum = sum + a()

350 NEXT n

360 END PROC

За именем массива должны идти скобки, чтобы интерпретатор отличал имена массивов от обычных переменных с тем же именем. Перед "sum" стоит оператор REF, так что по окончании работы содержимое "sum" будет передано глобальной переменной. Функция LENGTH (), о которой мы еще будем говорить, определяет размер массива для того, чтобы процедура могла работать с массивами любой длины.

Теперь зададим сам массив, чтобы убедиться, что наша процедура работает нормально:

100 DIM t(10)

110 FOR n=1 ТО 10

120 LET t(n)=n

130 NEXT n

и добавим вызов нашей процедуры:

140 total t(), answer

150 PRINT answer

в итоге получим 55.

Передача параметров списком

Возможны варианты, когда вам вместо того, чтобы определять комбинацию параметров для процедуры, удобнее иметь дело со списком этих параметров, причем список может быть неопределенной длины. Чтобы это было возможным, в БЕТА БЕЙСИКе 3.0 есть специальные средства.

Если в операторе DEF PROC использовать оператор DATA вместо обычного перечисления формальных параметров, то соответствующий ему оператор READ примет список фактических параметров, стоящих в вызове вашей процедуры. Чтобы эта возможность была по настоящему удобной, необходимо, чтобы можно было определить в процедуре есть ли еще параметры в списке, которые она не приняла. Для этого существует функция ITEM(). Она возвращает 0, если список исчерпан полностью, 1 если в списке есть не переданные параметры и следующий параметр число, 2 если следующий параметр строковая переменная.

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

100 DEF PROC SUM DATA

110 S = 0

120 DO UNTIL ITEM()=0

130 READ a

140 s = s+a

150 LOOP

160 PRINT sum

170 END PROC

Примененные в строках 120, 150 операторы DO UNTIL и LOOP это удобная форма

организации цикла (см. далее). В принципе вместо DO UNTIL можно было бы применить и DO WHILE (см. ниже).

Вызов этой процедуры можно выполнить, например так: sum 1, 2, 3, 4 или с других количеством параметров: sum 1, 2, х, у, z, 1256

Если Ваш список параметров состоит из строковых переменных, то в строке 130 надо было бы применять READ а$, а не READ a. А как быть, если список смешанный и содержит и числа и строки? В этом случае перед READ надо проверить, очередной параметр с помощью ITEM() и использовать либо тот вариант, либо другой. В строковых переменных при этом можно избежать использования кавычек, если вместо READ использовать READ LINE (см. далее).

Обратите внимание на то, что список фактических параметров, передаваемых через DATA и READ, исключает возможность им быть локальными, если Вы специально это не зададите.

Рекурсия

Процедура, которая вызывает саму себя, называется рекурсивной. Есть анекдот, что в одном из компьютерных словарей справочников написали:

РЕКУРСИЯ см. РЕКУРСИЯ.

Рекурсия часто помогает очень элегантно избегать сложных программистских проблем. С другой стороны, это не самая быстро работающая структура. К тому же возможны большие расходы памяти. Ведь при каждом вызове процедурой самой себя формируется новый временный список локальных переменных и для них выделяется память. Кроме того, несмотря на внешнюю простоту такой структуры, ее тщательный разбор может вызвать у программиста легкое головокружение. В качестве примера мы приведем процедуру, которая рисует бриллиант, а затем еще один такой же, но поменьше. Внутри первого и еще один внутри второго и так далее, на минимальный размер наложено ограничение, иначе процесс мог бы продолжаться бесконечно.

100 DEF PROC diamond х,y,size,diff DEFAULT diff=15

PLOT x,y, size DRAW size,size DRAW size,size DRAW size, size DRAW size, size

110 IF size >4 THEN

diamond x,y+size,size diff diamond x,y size,size diff diamond x size,y,size diff diamond x+size,y,size diff

130 END PROC

Вызвать эту процедуру можно, например, так: diamond 128,88,40

Ошибки

Если Вы попробуете вызвать процедуру, которую забыли задать, Вам дадут сообщение об ошибке W: "Missing DEF PROC". Если же Вы забудете закрыть процедуру с помощью END PROC сообщение X: "No END PROC". Программа будет стараться во время работы "перепрыгнуть" через блок, в котором задается процедура и не сможет этого сделать.

Если при вызове задано больше фактических параметров, чем их есть в наличии в описании процедуры, сообщение "Parameter error." Если тип формальных параметров не совпадает с типом реально установленных фактических параметров "Nonsense in BASIC". Оператор END PROC может генерировать сообщение "Variable not found", если оказывается, что переменная, которую процедура должна передать в качестве выходного параметра, не существует.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]