Языки программирования: Мега-Бейсик, Бета-Бейсик, Бета-Бейсик, Лазер-Бейсик, ZX-Форт, Паскаль HP4TM 1993 г.

BETA-BASIC - функции. Приложения.


9. ФУНКЦИИ

БЕТА-БЕЙСИК версии 3.0 имеет более 20 новых функций. Эти функ-
ции определены в нулевой строке (которая при листинге не восприз-
водится). Там же содержится и указание на машинный код, выпол-
няющий непосредственные расчеты для этих функций.

В программе эти функции существуют как обычные функции,
заданные пользователем, а в листинге они являются обычными ключевыми
словами. Например, если строка программы содержит FN S$, в листинге
это проявляется, как STRINGS и курсор проскакивает это слово за одно
нажатие. Функции, заданные пользователем и не являющиеся составной
частью БЕТА-БЕЙСИКа,. действуют как обычно.

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

Ввод имен функций БЕТА-БЕЙСИКа может осуществляться полностью
(если Вы работаете в режимах KEYWORDS 3 или 4) или вводом FN, затем
буквы, а затем символа "$" или символа "(". "FN" можно получить
нажатием клавиши "Y" в графическом режиме или по буквам.

Дополнительные функции БЕТА-БЕЙСИКа не будут работать, если в

памяти отсутствует машиннокодовая часть программы БЕТА-БЕЙСИК. С
другой стороны, если будет отсутствовать нулевая строка, то будут
потеряны определения функций и Вы получите сообщение об ошибке "FN
without DEF". В этом случае остальная часть языка будет работать,
но воспользоваться новыми функциями Вы не сможете.

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

Если же Вы захотите специально удалить нулевую строку, то это
можно сделать командой DELETE О ТО О.

Ниже мы приводим список новых функций БЕТА-БЕЙСИКа.

AND

FN A(

MEM

FN M(

BIN$

FN B$

MEMORY$

FN MS

CHAR$

FN C$

MOD

FN V(

COSE

FN C(

NUMBER

FN N (

DEC

FN D (

OR

FN 0(

DPEEK

FN P(

RNDM

FN R (

EOF

FN E (

SCRN$

FN K$

FILLED

FN F (

SHIFTS

FN Z$

HEX$

FN H$

SINE

FN S(

INARRAY

FN U(

STRINGS

FN S$

INSTRING

FN I(

TIMES

FN T$

ITEM

FN T(

USINGS

FN U$

LENGTH

FN L (

XOR

FN X(

AND (число, число)
FN А (число, число)

По написанию эта функция похожа на обычное ключевое слово AND,
но в программе их можно различить по различному синтаксису. Она
выполняет побитную операцию AND для двух чисел от О до 65535. Если
какой-то бит и в первом числе и во втором равен единице, то только в
этом случае соответствующий бит результата тоже будет равен единице.
Если хотя бы один из них равен нулю, то и в результате этот бит
будет равен нулю.

Чтобы лучше понять, как все это происходит, мы воспользуемся
функцией BIN$, о которой речь пойдет ниже.

BIN$ (254) = "11111110"
BIN$ (120) = "01111000"

BIN$(AND(254,120)) = "01111000"

Таким образом, с помощью функции AND можно выключать
(маскировать) нежелаемые биты. Например:

PRINT AND(BIN 00000111, ATTR(1ine,column))

Эта конструкция позволит получить значение INK, установленное
для знакоместа с координатами (line, column), а прочие цветовые
атрибуты в байте окажутся замаскированы. Поскольку BIN 00000111 = 7,
то мы .могли записать эту команду и так:

PRINT AND (7,ATTR(line,column))

Нижеприведенный пример напечатает на экране слово "Bang", если
на клавиатуре будет нажата клавиша "F". При этом не имеет значения,
какие еще клавиши будут нажаты вместе с ней. В примере клавиатура
рассматривается как серия внешних портов. Если Вы не знакомы с тем,

как это происходит, читайте нашу книгу ("Программирование в машинных

кодах"; М:, "ИНФОРКОМ",1990, 1992).

10 IF AND(BIN 00001000, IN 65022) = 0 THEN PRINT "Bang! ";

20 GO TO 10

BIN$ (число)
FN B$ (ЧИСЛО)

Функция дает двоичный эквивалент для заданного числа в виде
восьмисимвольной строки, если число меньше 256 или в виде шест-
надцатисимвольной строки, если число больше 255, но меньше 65535.
Речь идет только о целых числах.

Эта функция очень полезна для тех, кто осваивает программирова-
ние в машинных кодах и (или) пользуется функциями БЕТА-БЕЙСИКа для
битовых операций AND, OR, XOR.

Кроме того, эта функция может пригодиться при работе с генера-
тором символов, с графикой пользователя UDG и при анализе цветовых
атрибутов, системных переменных или при опросе клавиатуры, например:

10 PRINT AT 10,10; BIN$(IN65022)

20 GO TO 10

Символьная строка, выдаваемая этой функцией, - это последова-
тельность нулей и единиц. Может быть, Вам захочется, чтобы это были
иные символы. Например, при распечатывании на экране конструкции
шрифта знакогенератора очень удобно вместо единиц иметь крестики, а
вместо нулей - пробелы. Это тоже можно сделать, если принудительно
заслать (РОКЕ) в ячейку 62865 код буквы "X", а в ячейку 62869 - код
пробела " ".

CHAR$ (ЧИСЛО)
FN С$ (число)

Эта функция позволяет конвертировать целые числа до 65535 в
двухсимвольные строки, что позволяет более экономно использовать
память и более компактно хранить данные. Эквивалентом из обычного
БЕЙСИКа будет следующая конструкция:
LET а = INT(number/256):
LET b = number - a*2 56
LET c$ = CHR$ a + CHR$ b

Полученная в результате строка не всегда может быть
распечатана, т.к. не всегда в результате получается печатный сийвол.
В этом случае может, например, появиться сообщение об ошибке
"Invalid colour", если в итоге получился символ, являющийся
управляющим кодом. Перед печатью на экран желательно сделать
обратную конверсию. Это может сделать функция NUMBER, которая
заменит двухсимвольную строку на соответствующее ей число.
Поскольку на хранение двухсимвольной строки расходуются только два
байта, а не пять, как на число, то мы рекомендуем Вам очень серьезно
подумать о том, чтобы использовать эти возможности, если Ваша
программа обслуживает и хранит большие массивы чисел (что часто
бывает в научных расчетах).

Если Вы не можете работать только с целыми числами, то попро-
буйте воспользоваться преобразованием их. Например, Вам надо
хранить число 87.643. Умножив его на 100, Вы получите 8764.3
Округлите и преобразуйте 8764 в двухсимвольную строку перед со-
хранением этого числа в памяти. Когда же оно вновь Вам понадо-
бится, сделайте обратное преобразование. С помощью NUMBER
преобразуйте двухсимвольную строку в 8764 и поделите результат на

100. Полученное значение 87.64 имеет неплохую точность по сравнению
с исходным числом, эта точность достаточна для большинства
практических приложений.

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

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

100 DIM А$ (500,2)
110 FOR i = 1 ТО 500
120 LET a$(i) = CHR$ (i*10)
130 NEXT i

140 PRINT "Array is redy!"

150 PRINT "Press any key!"

160 PAUSE 0

170 FOR i= 1 TO 500

180 Print i, NUMBER(A$(i))

190 NEXT i

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

Оператор SORT работает с конвертированными в символьные стро-
ки массивами совершенно правильно.

COSE (число)
FN С (число)

Это функция "косинус". Она отличается от функции COS стан-
дартного БЕЙСИКа тем, что имеет меньшую (но достаточную в боль-
шинстве практических приложений) точность, зато выполняется в шесть
раз быстрее.

DEC (символьная строка)
FN D (символьная строка)

См. также НЕХ$ (число).

Эта функция преобразует символьную строку, выражающую шест-
надцатиричное число в целое десятиричное число от 0 до 65535. При
этом шестнадцатиричное число должно быть выражено символьной строкой
длиной от 1 до 4-х символов, а регистр символов - не имеет значения.

DEC ("FF") = 255

DEC ("10") = 16

DEC ("4000") = 16384

DEC ("e") = 14

Эта функция предназначена для обеспечения ввода в программу
шестнадцатиричных данных. Например:

INPUT а$: POKE address,DEC(a$)

Использование "пустой строки" или строки, содержащей символы,
не являющиеся шестнадцатиричной формой записи дает сообщение об
ошибке "Invalid argument".

DPEEK (адрес).

FN P(адрес).

См. также DPOKE.

Функция DPEEK - это то же самое, что и двойной РЕЕК. Эквива-
лентом этой функции в стандартном БЕЙСИКе является выражение:
LET а = РЕЕК (addr) + 256*РЕЕК (addr+1)

Таким образом, эта функция выдает содержимое двух следующих
друг за другом байтов. Обратите внимание на то, что младший байт
идет первым. Это очень удобно для проверки содержимого системных
переменных и при анализе машинно-кодовых процедур. Например:
10 LET nxt = DPEEK(23637): POKE nxt+5,65
20 REM xxxxx

В десятой строке будет прочитано содержимое системной пере-
менной NXTLN, после чего в результате РОКЕ первый символ, сле-
дующий после оператора REM будет изменен на символ "А". Сдвиг на +5
байтов в строке 20 необходим для того, чтобы пропустить номер строки
(2 байта), длину этой строки (2 байта) и код самого оператора REM (1
байт) .

Оператор DPOKE обеспечивает двойной РОКЕ точно так же, как
функция DPEEK обеспечивает двойной РЕЕК.

EOF (номер потока).

FN Е(номер потока).

Название функции EOF происходит из сокращения End of File
(конец файла). При работе с микродрайвом эта функция говорит о том
прочитан или нет последний байт из загружаемого файла.

Поток, номер которого указан в функции, должен быть предвари-
тельно открыт (OPEN#) для данного файла, содержащегося на ленте
микродрайва. Если этого не сделать, то Вы получите сообщение об
ошибке "Invalid Stream". Этот файл должен, конечно, физически
существовать и быть открытым для чтения. Иначе вы получите сообще-
ние об ошибке "Reading a "Write" file".

Функция выдает "1", если последний байт данных считан из фай-
ла или "0", если он еще не считан. Это помогает точно установить
момент конца считывания данных и избежать попыток прочтения большего
количества данных, чем в этом файле есть, что вызвало бы появление
ошибки.

Предположим, что на микродрайве у Вас есть файл "data".
Наиболее элегантный путь использования функции EOF выглядел бы так:
10 OPEN #5,"m",1,"data"
20 DO UNTIL EOF(5)=1
30 INPUT #5;a$: PRINT a$
40 LOOP
50 STOP

Впрочем, строку 20 можно записать еще короче:
20 DO UNTIL EOF(5)

Если Вы еще не привыкли к использованию циклов DO...LOOP, то
можете попробовать действовать так:
10 OPEN #5,"m",1,"data"
20 INPUT #5;a$: PRINT a$
30 IF EOF(5)=0 THEN GO TO 20
40 STOP

FILLED ().

FN F().

См. также команду FILL.

Эта функция дает количество пикселов, включенных по последней
команде FILL. Например:

10 PLOT 0,0: DRAW 9,0: DRAW 0,9
20 DRAW -9,0: DRAW 0,-9
30 FILL 5,5
40 PRINT FILLED()

Длина стороны квадрата - 10 пикселов. (Мы давали число 9 в
команде DRAW, но поскольку реальная линия на экране имеет толщину не
менее одного пиксела, то и сторона квадрата у нас будет десять
пикселов.) Внутренняя неокрашенная часть квадрата будет иметь
линейный размер по 8 пикселов на сторону. И функция FILLED() даст
нам значение 64.

Если Вы попробуете в строке 30 дать команду на стирание нарисо-
ванного квадрата:

30 FILL ,PAPER; 5,5
то функция FILLED() даст Вам результат - 100.

Разница между 100 и 64 - количество пикселов, ушедших на
изображение периметра квадрата.

НЕХ$ (число).

FN Н(ЧИСЛО).

См. также функцию DEC(строка).

Эта функция конвертирует десятиричный числовой аргумент в
шестнадцатиричную символьную строку. Строка имеет два символа, если
число было в диапазоне от -255 до +255 или четыре символа, если
абсолютная величина числа была больше. Если же число по абсолютной
величине больше, чем 65535, то выдается сообщение об ошибке "Integer
out of range".

HEX$ (32) = "20"
HEX$ (255) = "FF"
HEX$ (512) = "200"
HEX$. (-64) = "CO"
HEX$ (-1024)= "FC00"

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

Эта функция очень удобна, если Вам надо распечатать содержимое
памяти в шестнадцатиричном виде:

10 INPUT "Start address? "; addr

20 PRINT HEX$ (addr);" "; HEX$ (PEEK addr)

30 LET addr=addr+l: GO TO 10

Если же Вы хотите и начальный адрес при вводе тоже задавать в
шестнадцатиричном виде, то можете переделать строку 10 например так:
10 INPUT "start address? "; А$: LET addr = DEC (A$)

INARRAY (строковый массив(начальный элемент)
<,границы>,искомая строка).

FN и (строковый массив(начальный элемент)
<,границы>,искомая строка).

См. также функцию INSTRING.

Функция INARRAY осуществляет сканирование строкового массива в
поисках заданной строки. Если она не найдена, то выдается 0. Если же

она разыскана, то выдается номер той строки в массиве, в которой
данная символьная последовательность встретилась впервые.

В принципе функция INARRAY - разновидность функции INSTRING,
но предназначенная для работы с массивами, поэтому будет неплохо,
если Вы сначала прочитаете про работу функции INSTRING.

Нижеприведенный пример показывает, как можно разыскать все
символьные сочетания "howdy" в заданном массиве.
10 DIM а$(20,10)
20 LET а$(RND*19+1) = "howdy"
30 LET num=l
40 DO

50 LET num=INARRAY(a$(num),

"howdy")
60 EXIT IF num=0
70 PRINT num;" ";a$(num)
80 LET num=num+l
90 LOOP UNTIL num >20

В строке 50 выражение a$(num) при num=l предполагает, что поиск
начнется с первой строки массива. Когда первое искомое сочетание
символов будет найдено, строка, в которой оно содержится, будет вы-
дана на печать, после чего поиск будет продолжен с (п+1) строки.

Оператор EXIT IF выведет программу из цикла, когда уже не ос-
танется неразысканых сочетаний "howdy". Оператор LOOP UNTIL в строке
90 безусловно прекратит работу программы, когда все элементы
исходного массива будут просмотрены.

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

50 LET num=INARRAY(a$(num,3 TO 7),"howdy")

Эта возможность позволяет Вам разрабатывать и манипулировать с
базами данных. Например, Вам надо найти в базе все адреса, относя-
щиеся к городу Брест. Тогда Вы проведете поиск именно по тем
участкам информации, которые имеют отношение к полю "ГОРОД". И
исключите тем самым жителей города Москвы, проживающих на Брестс-
кой улице, поскольку поле УЛИЦА в розыск не попадет.

При поиске Вы можете использовать символ-заместитель "#", ко-
торый обозначает "любой символ". Это же, кстати, относится и к
функции INSTRING. Единственный случай, когда этот символ ничего не
замещает, а принимается сам за себя, - это когда он стоит первым
символом в искомой символьной строке.

Вы можете практиковать довольно сложные условия для поиска.
Например, у Вас в базе данных содержится список лиц с именами,
фамилиями, адресами, цветом волос и т.п. Если каждое поле начинает-
ся строго с фиксированной позиции, а так и должно и быть в
структурированной базе данных, то Вы можете найти всех содержащихся
в ней жителей Лондона, имеющих коричневый цвет волос. Для тех
позиций, которые соответствуют городу, Вы введете London, для тех,
которые соответствуют цвету волос - Brown, а для всех прочих
поставите символы "#".

Нижеприведенный пример покажет как это можно сделать. Здесь
первые 20 символов отведены под имя персоны, а последующие 15 - под
название города.

10 LET namelen=20, townlen=15
20 DIM d$(10,namelen+townlen)
30 FOR n=l TO 10
40 INPUT "name? ";n$
50 INPUT "town? ";t$
60 LET d$(n,1 TO namelen)=n$
70 LET d$(n,namelen+1 TO )=t$

80 NEXT n

90 PRINT "массив заполнен"

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

100 INPUT "name=? ";n$

110 INPUT "town=? ";t$

120 LET s$=n$ + STRING$(namelen-LEN n$,"#")+t$

130 LET loc=INARRAY(a$(l),s$)

140 IF loc=0 THEN

PRINT "Not found "

ELSE

PRINT loc;" ";d$(loc)

150 GO TO 100

Примечание: Функция INARRAY не может работать с массивами, раз-
мерность которых больше, чем 2.

INSTRING (старт, строка 1,строка 2).

FN I(старт,строкаг,строка2).

См. также функции: MEMORY$, INARRAY.

Функция INSTRING просматривает строку_1 в поисках строки_2, на-
чиная с символа "старт". Если такое вложение найдено, то функция
выдает порядковый номер символа в строке_1, с которого начинается
строка_2, в противном случае выдается ноль.

Первая строка может быть любой длины, а вторая - не более 256
символов, иначе будет выдано сообщение об ошибке "Invalid argument".
Если начальная позиция для поиска "старт" равна нулю, будет выдано
сообщение об ошибке "Subscript wrong".

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

В искомой строке можно использовать символ-заместитель "#",
который служит вместо тех символов, которые при поиске не имеют
значения. Например:

PRINT INSTRING (1,А$,"SM#TH")
найдет появление SMITH, SMYTH, SMATH и т.п. в символьной строке А$.

Единственный случай. когда символ "#" воспринимается бук-
вально, т.е. служит вместо самого себя - когда он стоит первым сим-
волом в искомой строке.

Возможность задания начальной позиции для поиска будет полезной
в тех случаях, когда Вы рассчитываете найти не одно, а большее
количество вхождений искомой строки в исходную. Ниже приведен
пример, который разыщет строку "TEST" в символьной строке А$.
100 DIM А$(1000)
110 FOR n=l ТО RND*10 + 3
120 LET pos = RND*995
130 LET A$ (pos TO pos + 3)
140 NEXT n

150 PRINT "Press any key"
160 PAUSE 0
170 LET loc=l

180 LET loc = INSTRING (loc,A$,"TEST")
190 IF loc <>0 THEN PRINT

"Found"; loc: LET loc=loc+l:
GO TO 180

200 PRINT "Finish"

Строка A$ начинает просматриваться с позиции 1 (1ос=1), пока не
будет найдена последовательность символов "TEST". После этого поиск
будет продолжен со следующего символа (1ос=1ос+1). Когда функция
выдаст 0, поиск будет завершен.

Обратите внимание на то, что строку 190 можно немного упрос-
тить :

190 IF 1ос THEN PRINT ...

Если Вам надо сделать поиск по оперативной памяти или по ее
части, Вы можете воспользоваться функцией MEMORY$.

Функцию INSTRING можно с успехом использовать в обучающих и в
некоторых игровых программах (в частности в адвентюрных). Предпо-
ложим, что программа задала пользователю вопрос, правильный ответ на
который хранится в переменной с$ = "NAPOLEON". Те, кто введут в
качестве ответа "NAPOLEON "(обратите внимание на финальный пробел)
или "NAPOLEON BONAPARTE", будут разочарованы, поскольку программа
воспримет эти ответы, как неправильные. А это очень часто
случается, если подпрограмма сравнения ответа и эталона не обладает
достаточной гибкостью. Функция INSTRING поможет справиться с этой
проблемой. Она оценит как правильный любой ответ, при котором
контрольная строка входит в состав введенной пользователем.

INPUT а$: IF INSTRING (1,а$,с$) о 0 THEN PRINT "Correct"

Вы можете решить при этом и проблему регистра, если заранее
не знаете большими или малыми буквами будет набран ответ поль-
зователя. Вам надо принудительно конвертировать его ответ в про-
писные буквы с помощью функции SHIFTS:

LET a$=SHIFT$(1,а$)

Еще одно возможное применение функции INSTRING - для упаковки
нескольких строк в одну длинную строку. При этом Вы можете, на-
пример использовать символы с 1-го по 31-ый в качестве "маркеров"
входящих строк.

Так, символ CHR$ 1 будет отмечать начало первой подстроки в
генеральной строке, символ CHR$ 2 - начало второй подстроки и так
далее. Так хранить строки гораздо компактнее, чем в массиве, если
они имеют неодинаковую длину. Найти строку с номером п в гене-
ральной строке будет несложно:

PRINT а$(INSTRING(1,а$,CHR$ n)+l ТО INSTRING (1,а$,CHR$(п+1))-1)

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

ITEM ()
FN Т()

См. также раздел, посвященный процедурам.

Эта функция дает информацию о следующей единице данных, которые
подлежат вводу через READ. Как правило, функция используется при
работе с процедурами, но может быть применена и при обычной тех-
нике READ...DATA. Функция возвращает следующие значения:

0 - все данные из текущего оператора DATA прочитаны. Текущий
оператор DATA может быть при этом и списком параметров, следующим за
вызовом процедуры.

1 - следующий объект - символьный.

2 - следующий объект - числовой.

При работе с процедурами функция 1ТЕМ() может дать информацию о
физической природе первого объекта данных, но во всех остальных
случаях она будет выдавать 0 до тех пор, пока хотя бы один объект не
будет считан из списка DATA с помощью READ. В нижеприведенном
примере проверяется 1ТЕМ() после READ.

100 DO

110 READ X

PRINT X
120 LOOP UNTIL ITEM()=0
130 DATA 1,2,3,4,5,6

Таким образом, строки 100 ... 120 могут считывать строки DATA
произвольной длины.

LENGTH (п,"имя массива")
FN L(n,"имя массива")

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

Параметр п определяет о какой размерности для двумерных масси-
вов идет речь. Если п=1, то функция возвращает размер массива в
первом измерении, а если п=2, то во втором измерении (или единицу,
если массив одномерный). С массивами размерности больше, чем 2, эта
функция работать не может.

В имени массива значимыми являются только первые два символа,
поэтому следующие имена будут приняты, как правильные: а$, Ь$, С(,
d(), a$QWERT. Если вместо имени массива ввести имя простой
символьной переменной, то она будет интерпретироваться как одно-
мерный массив, состоящий из односимвольных элементов. Количество
элементов при этом равно длине символьной строки. Примеры:
10 DIM а$(10,20)

20 PRINT LENGTH (1,"а$и): (10)
30 PRINT LENGTH (2,"а$"): (20)
40 DIM b(5)

50 PRINT LENGTH (l,"b(M): (5)
60 PRINT LENGTH (2,"b(M): (1)

Функция имеет еще одно замечательное свойство. Если вместо
параметра размерности массива ввести 0, то она выдаст адрес, в
котором в памяти компьютера расположен первый элемент массива или
символьной строки:

LENGTH (0, имя массива)
Эта возможность может быть использована теми, кто программирует
в машинных кодах - можно найти адрес, в котором хранятся те или иные
данные и даже можно найти адрес, с которого начинается процедура,
записанная в машинных кодах, если она оформлена, как массив данных.
Для тех же, кто программирует на БЕЙСИКе, имеется тоже немало
интересных приложений, особенно если этой функцией пользоваться
совместно с оператором РОКЕ и функцией MEMORYS. Так, например, можно
продублировать массив а$ в массиве Ь$, что может быть полезным при
реорганизации данных:

20 LET e=LENGTH(1,"а$")
30 LET f=LENGTH(2,"a$")
40 DIM b$(e,f)

50 LET start = LENGTH(0, "a$")

60 POKE LENGTH (0,"b$"), MEMORY$()(start TO start+e*f-l)
Примечание: Если Вы перебрасываете не символьный, а числовой
массив, то в строке 60 следовало бы вместо e*f
подставить 5*e*f, поскольку каждое действительное
число в "Спектруме" хранится в пятибайтной форме.
Приведенный выше алгоритм во многом отличается от команды Бе-

та-Бейсика COPY для массивов. Он, конечно, менее удобен, но может
служить неплохой основой для создания на его базисе быстро рабо-
тающей процедуры копирования массивов. Добавьте для этого строки:
10 DEF PROC dup REF а$, REF b$
70 END PROC

И теперь такая команда, как dup r$,t$ продублирует символьную
строку г$ в строке t$.

ЗАМЕЧАНИЕ ДЛЯ ОПЫТНЫХ ПОЛЬЗОВАТЕЛЕЙ

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

Без БЕТА-БЕЙСИКа Вы можете найти начало своего массива или
символьной строки, если дадите им такое имя, которое обеспечит им
первое место среди переменных в соответствующей области. Сделайте их
объявление первым в программе. Затем найдите искомый адрес:
PRINT PEEK 23627+256*РЕЕК 23628+d

Здесь d=3, если Вы ищете символьную строку; d=6, если Вы ище-
те начало одномерного массива и d=8, если массив - двумерный.

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

Примечание: Поскольку с помощью оператора LET могут создава-
ться новые символьные строки или изменяться ранее
существовавшие, то значения, ранее полученные
функцией LENGTH (0,"имяи) могут устаревать.

MEM ()
FN М()

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

PRINT МЕМ(): DIM а$(100):
PRINT MEM()

Эта простая функция содержит в себе в основном только вызов
процедуры из области ПЗУ. Если Вы работаете в стандартном БЕЙСИКе,
то выполнить ту же операцию можете командой:
PRINT 65535 - USR 7962

MEMORY$ ()
FN M$()

См. также РОКЕ симв. строка.

Эта функция выдает содержимое оперативной памяти компьютера в
виде символьной строки. Правда, при этом содержимое нулевой ячейки
памяти не включается. Поэтому команда CODE MEMORYS()(1) - то же
самое, что и РЕЕК 1. Последние три байта оперативной памяти также по
техническим причинам исключены, поэтому эта функция имеет
максимальную длину 65532.

Конечно, если Вы попробуете что-то типа: LET а$ = MEMORY$(), то
Вам не хватит оперативной памяти, чтобы разместить там переменную
а$, но пользоваться этой функцией надо по-другому. Например:
LET a$=MEMORY$()(16384 ТО 22527)

Если учесть способность БЕТА-БЕЙСИКа выполнять РОКЕ для сим-
вольных строк, то эта функция дает программисту возможность мани-
пуляций с большими блоками памяти при очень высокой скорости (в от-
личие от стандартного БЕЙСИКа). Более подробно возможности приме-
нения этой функции Вы найдете в разделе, посвященном оператору РОКЕ.

Другое применение MEMORY$ - для сканирования оперативной памяти
при использовании INSTRING. Вы можете просканировать заданную
секцию в памяти, указав пределы в функции MEMORY$()(23759 ТО ...).
Но функция INSTRING работает настолько быстро, что этим можно vt не
пользоваться, а сканировать по всей памяти целиком:

10 REM asdfg

20 PRINT INSTRING (1,MEMORY$(),"asdfg")

Эта программа найдет строку asdfg в операторе REM в строке 10.
Если Вы опустите строку 10, то asdfg будет найдена в строке 20.
Если Вы присвоите: LET а$ = "asdfg", то эта символьная строка будет
найдена в области программных переменных. Таким образом, где-ни-
будь в памяти, но Вы найдете содержимое любой символьной строки.

Вместо "1" в функции INSTRING мы могли бы дать DPEEK(23635),
т.е. содержимое системной переменной PROG для того, чтобы начинать
поиск не от начала ПЗУ, а с того, места, откуда начинается
БЕЙСИК программа.

Если же Вы хотите найти все случаи повторения в памяти задан-
ной последовательности символов (байтов), то можете делать так:

10 LET adr=l

20 LET adr=INSTRING(adr,MEMORY$(),a$)

30 IF adr<>0 THEN PRINT adr: LET adr=adr+l: GO TO 20

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

MOD (число,число)
FN V(число, число)

Эта функция дает остаток от деления первого числа на второе.

MOD (10,3) = 1

MOD (66,16) = 2

MOD (125,35.5) = 18.5

Нижеприведенный пример показывает, как можно избежать попыток
выполнения команды PLOT вне пределов экрана.
10 FOR п=0 ТО 400
20 PLOT MOD(n,256),MOD(n,176)
3 0 NEXT n

NUMBER (синв.строка)
FN N(синв. строка)

См. также CHAR$ (число).

Функция преобразует двухсимвольную строку в целое число от 0 до
65535. Эквивалентом в стандартном БЕЙСИКе является выражение:
LET num=2 56*CODE с$(1)+CODE с$(2)
Если символьная строка имеет более двух символов, выдается со-

общение об ошибке "Invalid argument".

С помощью функции CHARS функция NUMBER может применяться для
создания целочисленных массивов, в которых вместо чисел использо-
ваны их символьные эквиваленты.

OR (число, число)
FN О(число, число)

Эта функция произносится так же, как и обычное ключевое слово
"OR", но имеет другое действие. В программе или при вводе отличает-
ся иным синтаксисом.

Функция дает результат побитной логической операции "ИЛИ" для
двух чисел, каждое из которых находится в пределах от О до 65535.
Если какой-либо бит включен в первом или втором числе, то в ре-
зультате этот бит тоже включен (равен 1). Он будет равен О только
если он выключен в обоих числах одновременно.

RNDM (ЧИСЛО)
FN R(ЧИСЛО)

Если "число" равно О, то функция RNDM выдает случайное число от
О до 1 - точно так же, как и функция RND стандартного БЕЙСИКа. Если
же "число" не ноль, то функция выдает случайное целое число, лежащее
в диапазоне от нуля до заданного "числа".

Эта функция работает в два с половиной раза быстрее, чем рабо-
тало бы выражение RND*"4Hono".

10 PLOT RNDM(255),RNDM(175)
20 GO TO 10

Оператор RANDOMIZE "число" устанавливает генерируемую псевдо-
случайную последовательность в определенное положение точно так же,
как он делает это для функции RND в стандартном БЕЙСИКе.

SCRN$ (строка,столбец)
FN К$(строка,столбец)

Работает примерно так же, как и стандартная функция SCREENS, за
исключением того, что может распознавать и символы графики поль-
зователя UDG. Кроме того, исправлена ошибка системного ПЗУ, кото-
рая отражается на работе функции SCREENS. Об этой ошибке мы писали в
выпущенной "ИНФОРКОМом" книге "Элементарная графика". См. также
статью "Ошибки ПЗУ" в этом номере "ZX-РЕВЮ".

Перед тем, как набрать нижеприведенный пример, дайте команду
KEYWORDS 0. Программа распределит по экрану символы графики пользо-
вателя в виде случайного рисунка, а затем считает некоторые из них с
экрана.

10 FOR a=USR "а" ТО USR "и" + 7
20 РОКЕ а,RND*255
30 NEXT а

40 PRINT "символы графики пользователя"

50 LET а$ = ""

60 FOR с=1 ТО 31

70 LET а$ = а$ + SCRN$(0,c)

80 NEXT с

90 PRINT a$

Блочную графику "Спектрума" эта функция не распознает. Если
Вам и это необходимо, то запрограммируйте некоторые символы графики

пользователя так, чтобы они выглядели, как символы блочной графики.

Символы могут распознаваться только в том случае, если они
изображены в стандартном размере 8X8 пикселов (см. CSIZE).

SHIFT$ (число,строка)
FN Z$(число,строка)

SHIFTS - многоцелевая функция для преобразования строковых пе-
ременных. Она имеет много разных режимов работы. Режим задается
параметром "число" при вызове функции. Вот краткий обзор ее ре-
жимов .

1 - Все символы строки преобразуются в верхний регистр (в прописные

буквы).

2 - Все символы преобразуются в нижний регистр (в строчные буквы).

3 - Регистр всех символов меняется на противоположный.

4 - Подавление управляющих кодов. Все символы, являющиеся упра-

вляющими кодами, за исключением символа CHRS 13 (код ENTER)
заменяются символом "точка"(".").

5 - Подавление токенов ключевых слов. Символы CHR$ 128...255

заменяются символами О...127, при этом управляющие коды, за
исключением ENTER (CHR$ 13) заменяются символом "." .

6 - Подавление токенов ключевых слов. Символы CHR$ 128...255

заменяются символами О...127, при этом все управляющие коды
заменяются символом "." .

7 - Все ключевые слова преобразуются из токенизированной (од-

нобайтной) формы в многобайтную (по байту на каждый символ).

8 - Все ключевые слова преобразуются из формы с полным написанием в

однобайтные токены. Регистр символов роли не играет. После
каждого ключевого слова должен стоять небуквенный символ.

9 - То же, что и предыдущий режим, но после ключевого слова может

стоять любой символ.

10 - То же, что и предыдущий режим, но все ключевые слова должны

быть набраны прописными литерами.

11 - То же, что и режим 8, но все ключевые слова должны быть набраны

прописными буквами.

SHIFT$1...SHIFT$3

Прербразования регистров.
Рассмотрим примеры:
SHIFTS (1,"Basic") = "BASIC"
SHIFTS (2,"Basic") = "basic"
SHIFTS (3,"Basic") = "bASIC"

Обычное применение этих режимов - преобразование символьных
строк, вводимых пользователем, перед сравнением с контрольной
строкой в диалоговых программах.

100 INPUT iS: IF SHIFTS (l,i$)="Y" THEN GO TO 200
Это поможет Вам уйти от целой последовательности сравнений, та-
ких, как

IF i$ = "Y" OR i$ = "у"
При работе с базами данных, эта функция может использоваться
для того, чтобы предварительно конвертировать массив записей
пользователя в верхний регистр, прежде чем давать команду SORT.

SHIFT$4... SHIFT$6

Подавление управляющих кодов и токенов ключевых слов.
Эти режимы, по-видимому, найдут широкое применение у тех

пользователей, которые программируют в машинных кодах. Так, при
просмотре содержимого памяти компьютера, Вам может быть захочется
распечатать содержимое ячеек командой
PRINT CHR$(PEEK address)
Очень скоро по этой команде Вы получите сообщение" об ошибке
"Invalid colour". Это произойдет как только Вы попытаетесь распе-
чатать непечатный символ. Например, последовательность 17, 200
будет интерпретироваться, как CHR$17; CHR$200, а это в переводе с
машинного языка на БЕЙСИК означает PAPER 200. Компьютер отреагирует
сообщением об ошибке.

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

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

100 FOR П=1 ТО 65535 STEP 704

110 PRINT SHIFT$(6,MEMORY$()) (n TO n+703)

120 PAUSE 0: CLS

130 NEXT n

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

shift$7

Преобразование токенов в полную символьную запись.

Начнем с примеров:

10 LET а$ = " THEN NOT": REM это токены

20 PRINT а$, LEN а$: REM LEN=2

30 LET t$ = SHIFTS(7,a$)

40 PRINT t$, LEN t$: REM LEN=9

Эта функция должна быть полезной для тех, кто работает с
принтером. Если принтер подключен не через стандартный
"Синклеровский" интерфейс, то он не сможет воспроизводить на печать
токены ключевых слов БЕЙСИКа, поскольку он о них ничего не знает.

Подобная конверсия поможет Вам получать распечатки Ваших
БЕЙСИК-программ.

shift$8...shift$11

Преобразование ключевых слов из полной формы записи в
токенизированную форму.

Эта функция преобразует все символьные последовательности,
которые являются ключевыми словами БЕЙСИКа в токенизированную форму.
Ключевое слово не будет распознано, если непосредственно перед ним
стоит какая-либо буква. Что же касается символа, стоящего
непосредственно за ключевым словом, то его влияние зависит от того,
какой конкретно режим был избран (см. выше).

Эта функция может пригодиться в том случае, если Вы примете
БЕЙСИК-программу через внешний порт или через сеть от компьютера
другой системы. Конвертировав записанные символами ASCII ключевые
слова в токены и подправив синтаксис программы под свой "Спек-
трум", Вы сэкономите массу времени, т.к. Вам не придется набирать
текст программы вручную.

SINE (ЧИСЛО)
FN S(ЧИСЛО)

Это модифицированная функция "синус". Она дает менее точный
результат по сравнению с функцией SIN стандартного БЕЙСИКа, но зато
работает в шесть раз быстрее.

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

STRING$ (число,строка)
FN S$ (число,строка)

Эта функция дает строковую переменную, состоящую из параметра
"строка", повторенного столько раз, каково значение параметра
"число".

STRINGS (32,"-") = "--.....--" печатает 32 знака "-"

STRINGS (4,"АВ") = "АВАВАВАВ"

PRINT STRINGS(704,"X") - печатает экран, заполненный символами "X".
PRINT STRINGS (3,"A"+CHRS 13) печатает: А

А
А

Если Вам нужно сгенерировать строку, состоящую из более, чем 14
повторяющихся символов, то использовать STRINGS удобнее, чем вводить
символы от руки. Кроме того, функция STRINGS работает быстрее, чем
цикл FOR...NEXT, который тоже может быть применен для создания
длинной регулярной строки.

Эта функция может применяться в БЕТА-БЕЙСИКе для заполнения
блоков оперативной памяти информацией, например для установки
необходимых экранных атрибутов. Для этой цели она используется
совместно с функцией РОКЕ.

Т1МЕ$ ()
FN Т$()

См. также команду CLOCK.

Эта функция выдает текущие показания встроенных часов (если они
были инициализированы в БЕТА-БЕЙСИКе). Если Вы несколько раз
повторите команду PRINT TIMES (), то всякий раз получите разный ре-
зультат. В программах невредно передать показания часов какой-либо
переменной и, тем самым, "заморозить" полученный отсчет.

100 CLOCK 1

110 LET nS = TIMES(): PRINT n$

120 PRINT "Hours= "; n$(1 TO 2); "Mins = "; n$(4 TO 5)

130 GO TO 110

Так можно встроить в программу контроль за временем исполнения
программы пользователя. Подробности смотрите в разделе, посвя-
щенном описанию команды CLOCK.

USING$ (строка, число)
FN U$(строка, число)

См. также команду USING.

Функция конвертирует "число" в строковую переменную в формате,

заданном параметром "строка". Вы можете задать количество изобра-
жаемых символов до десятичной точки и после. Ключевое слово USING,
расположенное на клавише U обеспечивает то же самое в команде PRINT.
В отличие от него, функция USINGS позволяет не только распечатать
полученный результат, но и запомнить его. Она может быть
использована не только с командой PRINT, но и с другими командами,
допускающими работу со строковыми переменными. Более подробное
описание смотрите в разделе, посвященном команде USING.

XOR (число, число)
FN Х(число, число)

Функция выдает результат побитной операции "ИСКЛЮЧАЮЩЕЕ ИЛИ"
для двух чисел, которые должны быть в пределах от 0 до 65535. Если
какой-то бит и в первом числе и во втором равны между собой, то в
результате этот бит будет равен нулю. Если же они противоположны, то
в результате он будет равен единице.

ПРИЛОЖЕНИЕ 1.

КЛЮЧЕВЫЕ СЛОВА БЕТА-БЕЙСИКА.
Версия 3.0.

код

КЛАВИША

ТОКЕН

код

КЛАВИША

ТОКЕН

128

8

KEYWORDS

147

D

DO

129

1

DEF PROC

148

E

ELSE

130

2

PROC

149

F

FILL

131

3

END PROC

150

G

GET

132

4

RENUM

151

H

133

5

WINDOW

152

I

EXIT IF

134

6

AUTO

153

D

WHILE

135

7

DELETE

154

К

UNTIL

136

shift

7

REF

155

L

LOOP

137

shift

6

JOIN

156

M

SORT

138

shift

5

EDIT

157

N

ON ERROR

139

shift

4

KEYIN

158

0

ON

140

shift

3

LOCAL

159

P

DPOKE

141

shift

2

DEFAULT

160

Q

POP

142

shift

1

DEF KEY

161

R

ROLL

143

shift

8

CSIZE

162

S

SCROLL

144

A

ALTER

163

T

TRACE

145

В

164

U

USING

146

С

CLOCK

Примечание: Для того, чтобы вернуться к стандартному для
"Спектрума" значению вышеуказанных кодов, нужно
перейти в режим работы KEYWORDS 0.

ПРИЛОЖЕНИЕ 2.

СООБЩЕНИЯ ОБ ОШИБКАХ БЕТА-БЕЙСИКА. Версия 3.0.

в No room for line -

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

номерами больше 9999. Ошибка проявляется при работе команды RENUM.

S Missing LOOP -

Оператор цикла по условию DO WHILE, DO UNTIL или оператор
выхода из цикла EXIT IF не могут найти оператора конца цикла LOOP.
Ошибка проявляется при работе операторов DO WHILE, DO UNTIL, EXIT
IF.

T Loop without DO -

В программе присутствует оператор LOOP, но нет соответствую-
щего ему оператора DO.

U No such line -

В программе был использован оператор DELETE с указанием в
качестве параметра номера строки, которой в программе нет. Ошибка
проявляется при работе оператора DELETE.

V No POP data -

При попытке выполнить оператор POP оказывается, что стек GO
SUB/ DO-LOOP/PROC - пуст. Это означает, что в данный момент времени
не исполняются ни подпрограммы GO SUB ни циклы DO-LOOP, ни процедуры
PROC. Ошибка проявляется при исполнении оператора POP.

W Missing DEF PROC -

В программе была попытка исполнить процедуру, которая ранее не
была определена оператором DEF PROC. То же происходит, если раз-
личаются имена процедуры при задании и при вызове. Ошибка может
возникать, если встретился оператор END PROC, а процедура ранее не
была объявлена через DEF PROC. Ошибка проявляется при вызове
процедур и при исполнении операторов END PROC и LOCAL.

X No END PROC -

Программа во время работы пытается обойти объявление проце-
дуры, но не может найти оператора END PROC, который соответствовал
бы DEF PROC. Ошибка проявляется при встрече оператора DEF PROC.

ПРИЛОЖЕНИЕ 3.

КОДЫ ОШИБОК.

Ниже приведен список кодов, которые записываются в переменную
ERROR по команде ON ERROR. Список состоит из трех разделов. В пер-
вом разделе перечислены состояния, связанные со стандартным БЕЙСИКОМ
"Спектрума". Во втором разделе - ошибки БЕТА-БЕЙСИКА. В третьем
разделе - ошибки, связанные с ИНТЕРФЕЙСОМ-1.

Примечание: Коды 0 и 9 (а они фактически ошибками не являются)
не перехватываются оператором ON ERROR.

1. Для стандартного БЕЙСИКа.
Значение Код Сообщение

1. Для стандартного БЕЙСИКа.
Значение Код Сообщение

ERROR

ошибки

0

0

O.K.

1

1

NEXT without FOR

2

2

Variable not found

3

3

Subscript wrong

4

4

Out of memory

5

5

Out of screen

6

6

Number too big

7

7

RETURN without GOSUB

8

8

End of file

9

9

Stop statement

10

А

Invalid argument

11

В

Integer out of range

12

С

Nonsense in Basic

13

D

BREAK-CONT repeats

14

Е

Out of DATA

15

F

Invalid file name

16

G

No room for line

17

Н

STOP in INPUT

18

I

FOR without NEXT

19

J

Invalid I/O device

20

К

Invalid colour

21

L

BREAK into program

22

М

RAMTOP no good

23

N

Statement lost

24

0

Invalid stream

25

Р

FN without DEF

26

Q

. Parameter error

27

R

Tape loading error

2.ДЛЯ БЕТА-БЕЙСИКа

2.ДЛЯ БЕТА-БЕЙСИКа

28

S

Missing LOOP

29

T

LOOP without DO

30

и

No such line

31

V

No POP data

32

w

Missing DEF PROC

33

X

No END PROC

3. ДЛЯ ИНТЕРФЕЙСа-1.

3. ДЛЯ ИНТЕРФЕЙСа-1.

43

b

Program finished

44

с

Nonsense in BASIC

45

d

Invalid stream number

46

e

Invalid device expression

47

f

Invalid name

48

g

Invalid drive number

49

h

Invalid station number

50

i

Missing name

51

j

Missing station number

52

k

Missing drive number

53

1

Missing baud rate

54

m

Header mismatch error

55

n

Stream already open

56

о

Writing to a "read" file

57

P

Reading a "write" file

58

q

Drive "write" protected

59

r

Microdrive full

60

s

Microdrive not present

61

t

File not found

62

u

Hook code error

63

V

CODE error

64

w

MERGE error

65

X

Verification has failed

66

У

Wrong file type




СОДЕРЖАНИЕ:


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

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



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

Похожие статьи:
Сделай сам - Календарь на 1998 год.
Навины - была совершена попытка покушения на системного администратора Grodno C_Net :(
Вступление - содержание номера.
Письмо - Представляете, Мне пришло письмо из Москвы!!
Юмор - Анекдоты.

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