Инструменты пользователя

Инструменты сайта


msx:basic_programming_guide:04

Различия

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

Ссылка на это сравнение

msx:basic_programming_guide:04 [2020-03-21 22:51]
msx:basic_programming_guide:04 [2022-09-09 23:26] (текущий)
Строка 1: Строка 1:
-[<>​] +~~HIDEPAGE:​search;​sitemap~~ 
-~~TOC wide~~ +~~REDIRECT>msx:basic_dialogue_programming_language:004~~
- +
-====== Глава IV. Функции и подпрограммы ====== +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Любая по-настоящему полезная классификация +
-содержит от трёх до шести категорий. +
-<WRAP rightalign>​ +
-—//​Энон//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-В [[msx:basic:]] различают следующие основные типы функций:​ +
-  - встроенные функции:​ +
-    - встроенные числовые функции;​ +
-    - встроенные функции преобразования;​ +
-    - встроенные функции для работы со строками;​ +
-  - функции пользователя. +
- +
-Встроенные функции называют иначе //​стандартными//​ функциями,​ вычисление значений которых реализуется специальными программами,​ постоянно находящимися в памяти компьютера. Каждая такая программа имеет уникальное //имя//, по которому и происходит обращение к ней (''​SIN'',​ ''​LOG'',​ ''​VAL'',​ ''​MID$''​ и т.д.). +
- +
-К функциям //​пользователя//​ относятся те функции,​ которые пользователь определяет в программе сам. +
- +
-Заметим,​ что встроенные //​числовые//​ функции мы уже изучили (см. [[01#I.7.4. Операции — функции|раздел I.7.4.]])! +
- +
- +
-===== IV.1 Встроенные функции преобразования ===== +
- +
-Напомним,​ что множество значений строковых переменных — это множество упорядоченных наборов символов. Упорядоченность означает,​ что строковые значения различаются не только набором,​ но и последовательностью символов,​ например,​ "​краб"​ и "​брак"​ — это разные значения. Количество символов в значении строковой переменной меняется в пределах от 0 до 255. +
- +
-В дальнейшем,​ //​строкой//​ ''​A$''​ или //​словом//​ ''​A$''​ будем называть значение строковой переменной ''​A$''​. +
- +
-Обратим особое внимание на то, что строка может не содержать символов. Такая строка называется //​пустой//​ и обозначается %% ""​ %% (кавычки идут подряд). Длина этой строки равна 0. Не следует путать пустую строку со строкой,​ содержащей //​пустой//​ символ (пробел). Строка,​ содержащая пробел,​ обозначается %% " " %% (между кавычками есть пробел) и имеет длину 1.  +
-Отметим,​ что символ "​пробел"​ — равноправный с остальными символ! +
- +
-{{anchor:​len}} +
-==== IV.1.1. LEN–функция ==== +
-Её общий вид: +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-LEN(α) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: ​  +
-  * ''​LEN''​ ("​LENgth"​ — "​длина"​) — служебное слово;​ +
-  * α — строковое выражение. +
-Результатом функции LEN(α) является длина значения строкового выражения α (или что то же самое, количество символов в строке α), LEN(α)∈[0,​255]. +
- +
-Напомним,​ что в том месте дисплейной строки,​ где надо обратить Ваше внимание на наличие символа пробел (" "), мы будем использовать символ "​·"​((Примечание редактора:​ Это символ называется "​точка по центру"​ или "​знак умножения",​ подробнее [[https://​unicode-table.com/​ru/​00B7/​|здесь]] )). +
- +
-{{anchor:​e0411-01}} __//​Пример 1//__. \\ {{.examples:​0411-01.bas|}} \\ [[+tab|wmsxbpge>​0411-01.bas]] +
-<​code>​ +
-NEW +
-Оk +
-10 X$="​парк":​ Y$="​детский парк":​Z$="​ ау! ":​u$="":​w$="​ " +
-20 PRINT LEN(X$);​LEN(Y$);​LEN(Z$);​len(u$);​len(w$) +
-run +
-·4··12··5··0··1 +
-Ok +
-</​code>​ +
-Ещё раз подчеркнём,​ что //​пробел//​ — такой же символ,​ как, например "​а"​! +
- +
-Эта функция,​ пожалуй,​ чаще всего используется при работе со строковыми переменными. С её помощью,​ например,​ можно определить,​ не является ли строка пустой до выполнения действий,​ которые не могут выполняться над пустой строкой (%% ""​ %%). +
- +
-{{anchor:​e0411-02}} __//​Пример 2//__. \\ {{.examples:​0411-02.bas|}} \\ [[+tab|wmsxbpge>​0411-02.bas]] +
-  10 IF LEN(A$)>​0 THEN PRINT "​Все в порядке!"​ ELSE PRINT "​Строка пустая!"​ '​Проверка,​ является ли строка пустой,​ т.е. не содержащей ни одного символа. +
- +
-{{anchor:​e0411-03}} __//​Пример 3//__. \\ {{.examples:​0411-03.bas|}} \\ [[+tab|wmsxbpge>​0411-03.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 '​Выравнивание слов по правому краю. +
-20 FOR I=1 TO 3:READ A$ +
-30 ?​TAB(20-LEN(A$));​A$:​NEXTI +
-40 DATA "​Хакер-","​фанатичный","​программист"​ +
-run +
-··············Хакер- +
-··········фанатичный +
-·········программист +
-Ok +
-</​code>​ +
- +
-Сравните функцию ''​LEN()''​ с функцией __длин__(А),​ где __длин__(А) — длина текста A, в школьном алгоритмическом языке [[bibliography#​b11|[11,​ с.53]]]! +
- +
-{{anchor:​instr}} +
-==== IV.1.2. INSTR–функция ==== +
- +
-Общий вид функции:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-INSTR([n,​]α,​β) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: ''​INSTR''​("​IN STRing"​ — "в строке"​) — служебное слово;​ +
-  * n — арифметическое выражение,​ целая часть значения которого должна принадлежать [1,255] (по умолчанию n=1); +
-  * α — строковое выражение;​ +
-  * β — строковое выражение. +
-Эта функция исследует значение строкового выражения α слева направо,​ начиная с символа,​ номер которого задан величиной целой части значения параметра n или с его первого символа (по умолчанию). Значением функции является номер позиции в значении α, с которой значение β первый раз встречается в α. Если значение β не найдено,​ то результатом функции ''​INSTR''​ является 0 (как говорят,​ "​функция ''​INSTR''​ возвращает значение 0"). Значением выражения α или β может быть пустая строка. +
- +
-При работе с функцией ''​INSTR''​ возможны следующие ошибки. +
-Сообщение:​ <WRAP centeralign>"​Illegal ​ function ​ call" \\ (//"​Неправильный вызов функции"//​)</​WRAP>​ \\  +
-возникает,​ если значение арифметического выражения n неположительно,​ а сообщение:​ <WRAP centeralign>"​Type ​ mismatch"​ \\ (//"​Несоответствие типов"//​),</​WRAP>​ \\ если α или β нестрокового типа. Это сообщение выдаётся очень часто при работе с функциями преобразования и с функциями для работы со строками;​ как правило,​ причиной этого служит пропущенный знак "​$"​ после имени строковой переменной или имени строковой функции. +
- +
-__//​Пример//​__. +
-<​code>​ +
-NEW +
-Оk +
-10 INPUT X$,Y$,N +
-20 PRINT INSTR(N,​X$,​Y$) +
-run +
-? ХАФАНАНА,​НА,​3 +
- 5 +
-Ok +
- +
-run +
-? ХАФАНАНА,​НА,​100 +
- 0 +
-Ok +
- +
-run +
-? "","",​5 +
- 0 +
-Ok +
- +
-run +
-? KEN,"",​2 +
- 2 +
-Ok +
- +
-run +
-? Кузьма Кузьмич,​Кузьм,​1.5 +
- 1 +
-Ok +
- +
-run +
-? Кузьма Кузмич,​Кузьм,​0 +
-Illegal function call in 20 +
-Ok +
-</​code>​ +
- +
-{{anchor:​val}} +
-==== IV.1.3. VAL–функция ==== +
- +
-//​Цифровая//​ строка — это строка,​ содержащая любое количество расположенных в любом месте строки пробелов,​ знак "​плюс"​ или "​минус",​ десятичные цифры и десятичную точку. +
- +
-Цифровая строка также может содержать:​ +
-  - запись числа в экспоненциальном представлении (в форме с плавающей точкой);​ +
-  - запись числа в двоичном,​ восьмеричном и шестнадцатеричном представлениях;​ в этих случаях цифровая строка называется //​двоичной,​ восьмеричной и шестнадцатеричной//​ цифровой (символьной) строкой соответственно. +
- +
-В ряде случаев удобнее работать с числами,​ а не с их представлениями в виде цифровых строк. Цифровую строку можно преобразовать в числовое значение с помощью функции преобразования ''​VAL'',​ общий вид которой:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-VAL(α) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: ''​VAL''​("​VALue"​ — "​значение"​) — служебное слово;​ +
-  * α — строковое выражение. +
-Преобразование начинается с крайнего левого символа значения строкового выражения α и заканчивается,​ когда преобразован последний символ значения α, либо когда встретился нецифровой символ. +
- +
-__//​Примеры//​__:​ +
-<​code>​ +
-Ok +
-print VAL("​12.5E-3"​) +
-.0125 +
-Ok +
- +
-Ok +
-print val("&​b1"​);​val("&​o76"​);​val("&​hF"​) +
-·1··62··15 +
-Ok +
-</​code>​ +
-Если строка является пустой или начинается с нецифрового символа,​ то функция ''​VAL''​ возвращает значение 0. +
- +
-__//​Примеры//​__:​ +
- +
-  * 1)<​code>​ Ok +
-? VAL("​a12"​);​VAL("​23A12:"​);​VAL(""​) +
-·0··23··0 +
-Ok +
-</​code>​ +
-  * 2)<​code>​ Ok +
-? VAL("​-1.24"​) +
--1.24 +
-Ok +
-</​code>​ +
-Если одним из символов цифровой строки является восклицательный знак, то в зависимости от его расположения возможны следующие случаи. +
- +
-__//​Примеры//​__:​ +
-  * 1)<​code>​Ok +
-? VAL("​1234.56789!"​) +
-·1234.57 +
-Ok +
-</​code>​ результат преобразования:​ число одинарной точности (шесть значащих цифр!) +
-  * 2)<​code>​Ok +
-   ? VAL("​34!5.1"​) +
-   ​·34 +
-   Ok +
-</​code>​ +
-  * 3)<​code>​Ok +
-? VAL("​3456789!.7"​) +
-·3456790 +
-Ok +
-</​code>​ +
-  * 4)<​code>​Ok +
-? VAL("​!1"​) +
-·0 +
-Ok +
-</​code>​ +
-И наконец,​ парочка патологических случаев:​ +
-  * 5)<​code>​Ok +
-? VAL("&"​) +
-Syntax error +
-Ok +
-</​code>​ +
-  * 6)<​code>​ Ok +
-? VAL("&​H"​) +
- 0 +
-Ok +
-</​code>​ +
-Таким образом,​ функция ''​VAL''​ позволяет выделить цифры, входящие в значение строкового выражения,​ и образовать из них число для последующей математической обработки. +
- +
-{{anchor:​str}} +
-==== IV.1.4. STR$–функция ==== +
- +
-Часто бывает необходимо осуществить преобразование числа в цифровую строку,​ например,​ число 1234.56 преобразовать в цифровую строку %% "​1234.56"​ %%. +
- +
-Это преобразование осуществляет функция ''​STR$'',​ общий вид которой:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-STR$(α) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где:  +
-  * ''​STR''​ ("​convert to STRing"​ — "​преобразовать в строку"​) — служебное слово;​ +
-  * α — арифметическое выражение. +
-Данная функция преобразует значение арифметического выражения α в цифровую строку,​ что позволяет выделять и обрабатывать каждый символ (цифру) полученной строки с помощью //​строковых//​ (!) функций. +
- +
-__//​Примеры//​__ +
-  * 1)<​code>​ +
-Ok +
-print STR$(-15) +
--15 +
-Ok +
-</​code>​ +
-  * 2)<​code>​ +
-Ok +
-print STR$(1/3) +
-·.33333333333333 +
-Ok +
-</​code>​ +
-  * 3)<​code>​ +
-Ok +
-? STR$(1.E-3) +
-·1E-03 +
-Ok +
-</​code>​ +
-  * 4)<​code>​ +
-Ok +
-? STR$(&​b111);​STR$(&​o23);​STR$(&​HF1) +
-·7·19·241 +
-Ok +
-</​code>​ +
-Обратите //​особое//​ внимание на следующие примеры (первый символ в получаемых цифровых строках зарезервирован для указания знака числа):​ +
-  * 5) <​code>​ +
-Оk +
-? LEN(STR$(20)) +
-+
-Ok +
-</​code>​ +
-  * 6) <​code>​Ok +
-? LEN(STR$(-56.20)) +
-+
-Ok +
-</​code>​ +
-  * 7)<​code>​ +
-Оk +
-? LEN(STR$(-5620)) +
-+
-Ok +
-</​code>​ +
-  * 8)<​code>​ +
-Ok +
-? LEN(STR$(1.2E-27) +
-+
-Ok +
-</​code>​ +
- +
-Ещё один пример использования функции ''​STR$'':​ оператор +
-  PRINT n;"​X"​ +
-выводит на экран дисплея пробел между последней цифрой значения арифметического выражения n и символом "​X"​. Для исключения этого пробела воспользуйтесь оператором +
-  PRINT STR$(n);"​X"​ +
- +
-  * 9)<​code>​NEW +
-Ok +
-10 INPUT N +
-20 PRINT N;"​i"​ +
-30 ? STR$(N);"​i"​ +
-run +
-? 10 +
-10 i +
-10i +
-Ok +
-</​code>​ +
-  * 10) <​WRAP><​code>​NEW +
-Ok +
-10 INPUT N +
-20 PRINT "​i";​n +
-30 ?"​i";​MID$(STR$(N),​2) +
-run +
-? 10 +
-i 10 +
-i10 +
-Ok +
-</​code>​ +
-(о строковой функции ''​MID$()''​ см. в [[#IV.2.1. MID$–функция|разделе IV.2.1.]]). +
-</​WRAP>​ +
- +
-Отметим,​ что обычно в программах функции ''​VAL()''​ и ''​STR$()''​ используются совместно. +
- +
-  * 11) <​code>​ +
-Ok +
-input N$:print STR$(VAL(N$)) +
-? 23123.45 +
-·23123.45 +
-Ok +
- +
-? -4.7 +
--4.7 +
-Ok +
- +
-? &HFF +
-·255 +
-Ok +
- +
-однако… +
-? 12ABBA +
-·12 +
-Ok +
-</​code>​ +
-  * 12) <​code>​ +
-Ok +
-input N:print VAL(STR$(N)) +
-? 12 +
-·12 +
-Ok +
- +
-? -14.6E-2 +
--.146 +
-Ok +
- +
-? &b111 +
-·7 +
- +
-Ok +
- +
-? &o21 +
-·17 +
-Ok +
- +
-? &h1E +
-·30 +
-Ok +
-</​code>​ +
-  * {{anchor:​e0414-13}} <​WRAP>​ 13) найдите натуральные числа, не превосходящие заданного N и равные сумме кубов своих цифр. +
-\\ {{.examples:​0414-13.bas|}} \\ [[+tab|wmsxbpge>​0414-13.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT N +
-20 FOR I=1 TO N +
-30 A$=STR$(I):​S=0 +
-40 FOR J=2 TO LEN(A$) +
-50 S=S+VAL(MID$(A$,​J,​1))^3 +
-60 NEXT J +
-70 IF S=I THEN PRINTI;:​NEXT I ELSE NEXT I +
-run +
-? 400 +
-·1··153··370··371 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e0414-14}} <​WRAP>​ 14) определите наибольшую из цифр, используемых в десятичной записи натурального числа M. +
-\\ {{.examples:​0414-14.bas|}} \\ [[+tab|wmsxbpge>​0414-14.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT I +
-20 A$=STR$(I) +
-30 M=VAL(MID$(A$,​2,​1)) +
-40 FOR J=2 TO LEN(A$)-1 +
-50 IFM<​VAL(MID$(A$,​J+1,​1))THEN M=VAL(MID$(A$,​J+1,​1)):​NEXTJ ELSE NEXTJ +
-60 PRINT M +
-run +
-? 789103 +
- 9 +
-Ok +
- +
-run +
-? 7777777777777777 +
- ​8 ​        ▲ +
-Ok         │ +
-       16 символов +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e0414-15}} <​WRAP>​ 15) найти наибольшую из цифр, встречающуюся в десятичной записи данного натурального числа M более одного раза. +
-\\ {{.examples:​0414-15.bas|}} \\ [[+tab|wmsxbpge>​0414-15.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT M +
-20 N$=STR$(M) +
-30 FOR I=2 TO LEN(N$)-1 +
-40 FOR J=I+1 TO LEN(N$) +
-50 IF MID$(N$,​I,​1)=MID$(N$,​J,​1) THEN IF VAL(MID$(N$,​I,​1))>​A THEN A=VAL(MID$(N$,​I,​1)):​NEXTI ELSE ELSE NEXTJ:​NEXTI +
-60 PRINT A +
-run +
-? 1234245 +
- 4 +
-Ok +
- +
-run +
-? 1243.67E34 +
- 7 +
-Ok      +
- +
-Последний результат вызывает удивление,​ не правда ли? +
-Однако… +
-print n$ +
- ​1.24367E+37 +
-Ok +
-и все становится ясным! +
-</​code>​ +
-</​WRAP>​ +
- +
-{{anchor:​asc}} +
-==== IV.1.5. ASC–функция ==== +
- +
-Напомним,​ что при вводе в ЭВМ символы преобразуются в соответствии с кодом ASCII (см. [[01#I.7.3. Строковые операции|раздел I.7.3.]]). +
-Функция +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-ASC(α) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где:  +
-  * ''​ASC''​("​ASC"​ — "​American Standard Code") — служебное слово;​ +
-  * α — строковое выражение,​ +
-даёт возможность установить десятичный код ASCII первого символа значения строкового выражения α. Результатом функции ''​ASC''​ является целое число из отрезка [0,255] (говорят,​ что функция ''​ASC''​ //​возвращает//​ целое число из отрезка [0,255]). +
- +
-__//​Пример//​__. +
-<​code>​ASC +
-NEW +
-Ok +
-10 INPUT X$:​Y=ASC(X$):​PRINT X$;Y +
-run +
-? π +
-π 163 +
-Ok +
- +
-run +
-? αδβ +
-αδβ 160 +
-Ok +
- +
-run +
-? ; +
-; 59 +
-Ok +
- +
-run +
-? ","​ +
-, 44 +
-Ok +
- +
-run +
-? ♪  ◀─ символ,​ +
-♪ 1     ​имеющий +
-Ok    двухбайтовый код +
-</​code>​ +
-Из приведённого примера ясно, что ​ символ "​π",​ например,​ имеет десятичный код 163, а символ "​α"​(первый символ значения строковой константы"​αδβ"​) — десятичный код 160. +
- +
-Далее, если значением строкового выражения α является пустая строка (%% ""​ %%), то фиксируется ошибка <WRAP centeralign>"​Illegal function call"​.</​WRAP>​ +
- +
-Используя предыдущий пример,​ попытаемся получить код символа %% " %% (кавычка). +
-<​code>​ +
-run +
-? " +
-Illegal function call in 10 +
-Ok +
-Неудача!… Попытаемся ещё разок… +
-run +
-? """​ +
-? Redo from start +
-? █   и т.д. +
-</​code>​ +
-Снова неудача! Не волнуйтесь,​ код символа "​кавычка"​ можно получить косвенным путём с помощью функции преобразования ''​CHR$''​. +
- +
-{{anchor:​chr}} +
-==== IV.1.6. CHR$–функция ==== +
- +
-Общий вид функции:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-CHR$(α) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где:  +
-  * ''​CHR''​("​CHaRacter"​ — "​символ"​) — служебное слово;​ +
-  * α — арифметическое выражение. +
- +
-Вначале компьютер вычисляет //код// — целую часть значения выражения α. Код должен принадлежать отрезку [0,255], иначе на экране появится сообщение об ошибке:​ <WRAP centeralign>"​Illegal function call"​.</​WRAP>​ +
- +
-Результатом функции ''​CHR$''​ является однобайтовая строка,​ содержащая символ,​ соответствующий полученному коду (говорят,​ что функция ''​CHR$''​ //​возвращает//​ однобайтовую строку,​ содержащую символ,​ соответствующий +
-полученному коду). +
- +
-__//​Примеры//​__:​ +
- +
-  * 1)<​code>​ +
-INPUT X:​Y$=CHR$(X):​PRINT X;Y$ +
-? 34 +
-  34 " +
-Ok +
- +
-? 187 +
-  187 √ +
-Ok +
- +
-? 163 +
-  163 π +
-Ok +
-</​code>​ +
-  * 2) переменной A$ присвоить значение "​A$=%%"​BANSAJ!"​%%"​ <​code>​ +
-A$="​A$="​+CHR$(34)+"​BANSAJ!"​+CHR$(34) +
-А теперь… +
-print A$ +
-A$="​BANSAJ!"​ +
-Ok +
-</​code>​ +
-  * 3) вывести на экран дисплея текст: "​Нажмите клавишу %%"​SHIFT"​+"​1"​%%"​. <​code>​ +
-Ok +
-PRINT "​Нажмите клавишу ";​CHR$(34);"​SHIFT";​CHR$(34);"​+";​CHR$(34);"​1";​CHR$(34) +
-Нажмите клавишу "​SHIFT"​+"​1"​ +
-Ok +
-</​code>​ +
-  * {{anchor:​e0416-04}} <​WRAP>​ 4) инициализация строкового массива ''​B$(N)''​ "​псевдослучайными"​ словами +
-\\ {{.examples:​0416-04.bas|}} \\ [[+tab|wmsxbpge>​0416-04.bas]] +
-<​code>​ +
-Ok +
-20 Z=RND(-TIME) +
-30 INPUT "​Введите наибольшее количество символов слова";​G +
-40 INPUT"​Введите количество слов";​N:​DIM B$(N) +
-60 FOR K=1 TO N:​A=INT((G+1)*RND(1)) +
-80 FOR I=1 TO A:​B$(K)=B$(K)+CHR$(INT(255*RND(1))) +
-100 NEXT I,K +
-110 FOR K=1 TO N:PRINT K;"​слово:​ ";​B$(K):​NEXT +
-run +
- +
-Введите наибольшее количество символов слова? 4 +
-Введите количество слов? 2 +
-1 слово: ▲щΓ +
-2 слово: X∞p +
-Ok +
-</​code>​ +
-</​WRAP>​ +
- +
-Функции ''​ASC()''​ и ''​CHR$()''​ являются взаимообратными,​ то есть ''​X=ASC(CHR$(X))''​ и ''​Y$=CHR$(ASC(Y$))'',​ если только значение арифметического выражения X находится в допустимых +
-пределах (напомним,​ что 0≤X≤255!),​ а ''​LEN(Y$)=1''​. +
-   * {{anchor:​e0416-05}} <​WRAP>​ 5) присвоить строковой переменной Y$ значение "​yes",​ если X≥1 и "​no"​ — если X<1. Оператор условного перехода ''​IF…THEN…ELSE…''​ не применять! +
-\\ {{.examples:​0416-05.bas|}} \\ [[+tab|wmsxbpge>​0416-05.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT X +
-20 Y$=CHR$(-(X>​=1)*ASC("​y"​))+CHR$(-(X>​=1)*ASC("​e"​))+CHR$(-(X>​=1)*ASC("​s"​))+CHR$(-(X<​1)*ASC("​n"​))+CHR$(-(X<​1)*ASC("​o"​)):​print Y$ +
-run +
-? 5 +
-yes +
-Ok +
- +
-run +
-? -1 +
-no +
-Ok +
-</​code>​ +
-</​WRAP>​ +
- +
-Наконец заметим,​ что функцию ''​CHR$''​ удобно использовать для работы с непечатаемыми "​символами"​ (<​key>​BS</​key>,​ <​key>​SELECT</​key>,​ <​key>'​Ввод '​⏎</​key>,​ клавиши управления курсором). +
- +
-{{anchor:​bin}} +
-==== IV.1.7. BIN$–функция ==== +
- +
-''​BIN$''​–функция применяется для преобразования целого числа в двоичную символьную строку. Её общий вид: +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-BIN$(α) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​BIN''​ ("​BINary"​ — "​двоичный"​) — служебное слово;​ +
-  * α — арифметическое выражение. +
-Вначале вычисляется значение арифметического выражения α; результат преобразуется в целое число (возможно со знаком);​ если это число не попадает на отрезок [-32768,​65535],​ то компьютер фиксирует ошибку переполнения:​ <WRAP centeralign>"​Overflow"​.</​WRAP>​ +
- +
-Полученное число записывается в двоичной системе счисления,​ а затем преобразуется в символьную строку,​ соответствующую его двоичному коду. +
- +
-Таким образом,​ +
-<​code>​ +
-Ok +
-? BIN$(3),​BIN$(0) +
-11············0 +
-Ok +
- +
-Ok +
-? BIN$(32767) +
-111111111111111 +
-Ok +
- +
-Ok +
-? BIN$(65536) +
-Overflow +
-Ok +
-</​code>​ +
-Максимальная длина строки результата функции ''​BIN$()''​ — 16. +
- +
-Обозначим целую часть значения выражения α буквой N. +
- +
-Заметим,​ что для отрицательных N компьютер вычисляет значение функции ''​BIN$(N)''​ по рекуррентной формуле:​  +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-BIN$(N)=BIN$(65536+N) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-__//​Примеры//​__:​ +
-  * 1)<​code>​ +
-BIN$(-1) ​    ​возвращает ​ "​1111111111111111",​ +
-BIN$(-32768) возвращает ​ "​1000000000000000",​ +
-BIN$(32768) ​ возвращает ​ "​1000000000000000",​ +
-BIN$(65535) ​ возвращает ​ "​1111111111111111"​. +
-</​code>​ +
-  * 2)<​code>​ +
-print VAL("&​B"​+BIN$(15)) +
-15 +
-Ok +
-</​code>​ +
-Наконец,​ при помощи функции ''​BIN$''​ можно "​научить"​ компьютер двоичной арифметике. Посмотрите,​ например,​ как работает следующая программа:​ +
-  * {{anchor:​e0417-03}} <​WRAP>​ 3) +
-\\ {{.examples:​0417-03.bas|}} \\ [[+tab|wmsxbpge>​0417-03.bas]] +
-<​code>​ +
-Ok +
-10 PRINT"​Могу найти сумму двух двоичных чисел!"​ +
-20 INPUT "​Первое число, второе число";​N1$,​N2$ +
-40 ANS=VAL("&​B"​+N1$)+VAL("&​B"​+N2$) +
-50 BN$=RIGHT$(STRING$(16,"​0"​)+BIN$(ANS),​16)'​См.аналогию в п. 1.9! +
-60 PRINT"​Ответом является:";​BN$;"​ или";​ANS;"​десятичное"​ +
-run +
-Могу найти сумму двух двоичных чисел! +
-Первое число, второе число? 1111111111111111,​1 +
-Ответом является:​0000000000000000 или 0 десятичное +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-Неизвестные Вам пока строковые функции ''​RIGHT$''​ и ''​STRING$''​ рассмотрены ниже в разделах [[#IV.2.3. RIGHT$–функция|IV.2.3]]. и [[#IV.2.4. STRING$–функция|IV.2.4]]. +
-  * {{anchor:​e0417-04}} <​WRAP>​ 4) среди простых чисел, не превосходящих N, найти такое, в двоичной записи которого максимальное число единиц. +
-\\ {{.examples:​0417-04.bas|}} \\ [[+tab|wmsxbpge>​0417-04.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT N +
-20 FOR I=1 TO N:FOR J=2 TO INT(SQR(I)) +
-40 IF IMODJ=0 GOTO 100 ELSE NEXT J +
-50 M$=BIN$(I):​PRINT I;M$:L=0 +
-60 FOR K=1 TO LEN(M$):IF MID$(M$,​K,​1)="​1"​ THEN L=L+1 +
-80 NEXTK +
-90 IF L>R THEN R=L:R1=I +
-100 NEXT I +
-110 PRINT R;R1 +
-run +
-? 18 +
-·1·1 +
-·3·11 +
-·5·101 +
-·7·111 +
-·11·1011 +
-·13·1101 +
-·17·10001 +
-·3··7 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e0417-05}} <​WRAP>​ 5) выделить старший и младший байты двоичного числа ''​A%''​ +
-\\ {{.examples:​0417-05.bas|}} \\ [[+tab|wmsxbpge>​0417-05.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT"​Введите число A% (не более 16 двоичных цифр)";​A% +
-20 IF A%<0 THEN H%=A%\256-1 ELSE H%=A%\256 +
-25 L%=A%MOD256 +
-30 PRINT RIGHT$("​00000000"​+BIN$(H%),​8);"​ ";​RIGHT$("​00000000"​+BIN$(L%),​8) +
-run +
-Введите число А% (не более 16 двоичных цифр)? &​B1011110001010011 +
-10111100 01010011 ​                              ▲ +
-Ok                                              │ число отрицательное! +
- +
-run +
-Введите число А% (не более 16 двоичных цифр)? &​B0011110001010000 +
-00111100 01010000 ​                              ▲ +
-Ok                                              │ число положительное! +
-</​code>​ +
-</​WRAP>​ +
- +
-{{anchor:​oct}} +
-==== IV.1.8. OCT$–функция ==== +
- +
-''​OCT$''​–функция служит для преобразования числа в восьмеричную символьную строку. Её общий вид: +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-OCT$(α) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где:  +
-  * ''​OCT''​ ("​OCTal"​ — "​восьмеричный"​) — служебное слово;​ +
-  * α — арифметическое выражение. +
-Эта функция вычисляет значение арифметического выражения α, преобразует результат в целое (возможно со знаком);​ если результат не принадлежит отрезку [-32768,​65535],​ то фиксируется ошибка:​ <WRAP centeralign>"​Overflow"​ \\ (//"​Переполнение"//​).</​WRAP>​ +
- +
-В противном случае результат преобразуется в символьную строку,​ представляющую его значение в восьмеричной системе счисления. +
- +
-Максимальная длина строки–результата ''​OCT$()''​ — 6 символов (6 байт). +
- +
-__//​Пример//​__. +
-<​code>​ +
-Ok +
-print OCT$(&​HFFFF) +
-177777 +
-Ok +
-</​code>​ +
- +
-Обозначим буквой N целую часть значения выражения α. +
- +
-Если N принадлежит диапазону [0,65535], то значение функции OCT$() находится компьютером без обращения к дополнительному коду, например:​ +
-<​code>​ +
-print OCT$(0) +
-+
-Ok +
- +
-print OCT$(65535) +
-177777 +
-Ok +
-</​code>​ +
-Если же N принадлежит диапазону [-32768,​-1],​ то значение функции ''​OCT$()''​ находится ЭВМ с использованием дополнительного кода, т.е. по рекуррентной формуле:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-OCT$(N)=OCT$(65536+N) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-Например:​ +
-  * 1)<​code>​ +
-Ok                            0k +
-print OCT$(-1) ​  ​сравните с   print OCT$(65535) +
-177777 ​                       177777 +
-Ok                            Ok +
-</​code>​ +
-  * 2)<​code>​ +
-Ok                            Оk +
-? OCT$(-32768) ​  ​сравните с   print OCT$(32768) +
-100000 ​                       100000 +
-Ok                            Ok +
-</​code>​ +
- +
-__//​Задача//​__. Попытайтесь научить компьютер "​восьмеричной"​ арифметике. Используйте для этой цели идею следующего фрагмента:​ +
-<​code>​ +
-print VAL("&​O"​+OCT$(100)) +
- 100 +
-Ok +
-И, наконец… +
-</​code>​ +
- +
-{{anchor:​hex}} +
-==== IV.1.9. HEX$–функция ==== +
- +
-''​HEX$''​–функция служит для преобразования целого числа в шестнадцатеричную символьную строку. Её общий вид: +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-HEX$(α) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​HEX''​ ("​HEXadecimal"​ — "​шестнадцатеричный"​) — служебное слово;​ +
-  * α — арифметическое выражение. +
-Вначале вычисляется N — целая часть значения арифметического выражения α. Если N не попадает на отрезок [-32768,​65535],​ то компьютер сообщает об ошибке:​ <WRAP centeralign>"​Overflow"​ \\ (//"​Переполнение"//​).</​WRAP>​ +
- +
-"​Правильное"​ N преобразуется в символьную строку,​ соответствующую его шестнадцатеричному коду. Максимальная длина результата ​ вычисления значения функции равна //​четырём//​ байтам (четырём символам). +
- +
-Если целое число N находится на отрезке [0,65535], то преобразование элементарно:​ +
-  * ''​HEX$(0)'' ​    ​возвращает "​0",​ +
-  * ''​HEX$(65535)''​ возвращает "​FFFF"​. +
-Однако,​ значение функции при отрицательных N, принадлежащих [-32768,​-1],​ вычисляется компьютером с использованием дополнительного кода, т.е. с применением рекуррентной формулы:​ +
-<​code>​ +
-     ​HEX$(N)=HEX$(65536+N);​ +
-    HEX$(-1)=HEX$(65535) возвращает "​FFFF";​ +
-HEX$(-32768)=HEX$(32768) возвращает "​8000"​. +
-</​code>​ +
-Функция ''​VAL()''​ в комбинации с функцией ''​HEX$()''​ позволяют получить обратное преобразование:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-N=VAL("&​h"​+HEX$(N)) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-//​Примеры//:​ +
-<​code>​ +
-Ok +
-? VAL("&​h"​+HEX$(3)) +
- 3 +
-Ok +
- +
-Ok +
-? VAL("&​H"​+HEX$(-10)) +
--10 +
-Ok +
-</​code>​ +
- +
-Существование функции ''​HEX$()''​ делает возможным "​обучение"​ компьютера шестнадцатеричной арифметике. Единственная трудность состоит в добавлении к числу нулей, стоящих в старших разрядах (если, конечно,​ это необходимо!). +
- +
-Подумайте!… Придумали?​ Если нет, то возьмите на вооружение следующий красивый приём:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-X$=RIGHT$("​0000"​+HEX$(N),​4) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-</​WRAP>​ +
-</​WRAP>​ +
- +
-или +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-X$=RIGHT$(STRING$(4,"​0"​)+HEX$(N),​4) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-//​Пример//​. +
- +
-  * {{anchor:​e0419-01}} <​WRAP>​ 1) +
-\\ {{.examples:​0419-01.bas|}} \\ [[+tab|wmsxbpge>​0419-01.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 PRINT"​Введите два шестнадцатеричных числа"​ +
-20 INPUT A$,B$ +
-30 SM=VAL("&​H"​+A$)+VAL("&​H"​+B$) +
-40 DF=VAL("&​H"​+A$)-VAL("&​H"​+B$) +
-50 PRINT "​Сумма,​ разность:";​RIGHT$("​0000"​+HEX$(SM),​4);​SPC(1);​RIGHT$("​0000"​+HEX$(DF),​4) +
-run +
-Введите два числа +
-? 1,1 +
-Сумма, разность:​0002 0000 +
-Ok +
- +
-run +
-Введите два числа +
-? F000,FFF1 +
-Сумма, разность:​EFF1 F00F +
-Ok +
- +
-run +
-Введите два числа +
-? FFFF,FFFF +
-Сумма, разность:​FFFE 0000 +
-Ok +
- +
-run +
-Введите два числа +
-? FFFFF,E +
-Overflow in 30 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e0419-02}} <​WRAP>​ 2) выделить старший и младший байты шестнадцатеричного числа ''​A%''​. +
-\\ {{.examples:​0419-02.bas|}} \\ [[+tab|wmsxbpge>​0419-02.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT "​Введите число А% (не более 4 шестнадцатеричных цифр)";​A% +
-20 IF A%<0 THEN H%=A%\256-1 ELSE H%=A%\256 +
-25 L%=A%MOD256 +
-30 PRINT RIGHT$("​00"​+HEX$(H%),​2);"​ ";​RIGHT$("​00"​+HEX$(L%),​2) +
-run +
-Введите число А% (не более 4 шестнадцатеричных цифр)? &​H67EA +
-67 EA                                                 ​───▲── +
-Ok                                    положительное число┘ +
-run +
-Введите число А% (не более 4 шестнадцатеричных цифр)? &​HE2A9 +
-E2 A9                                                 ​───▲── +
-Ok                                    отрицательное число┘ +
-</​code>​ +
-</​WRAP>​ +
-Теперь настало время подумать,​ почему встроенные функции,​изученные нами в разделах [[#IV.1.1. LEN–функция|IV.1.1.]] — IV.1.9. [[#​HEX$–функция|IV.1.9]],​ называются "​функциями преобразования"​. +
- +
-===== IV.2. Встроенные строковые функции ===== +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Пока слепо плыл сон по разбитым надеждам,​\\  +
-Космос с болью сочился над разбитой любовью,​\\  +
-Был из скрытных людей свет твой медленно изгнан,​\\  +
-И небо не спало. +
-<WRAP rightalign>​ +
-—//​Избранные стихотворения компьютера RCA–301, поэма 929// +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-В этом разделе мы рассмотрим следующие встроенные функции:​ ''​[[#​mid|MID$]]'',​ ''​[[#​left|LEFT$]]'',​ ''​[[#​right|RIGHT$]]'',​ ''​[[#​string|STRING$]]'',​ ''​[[#​space|SPACE$]]''​. +
- +
-{{anchor:​mid}} +
-==== IV.2.1. MID$–функция ==== +
- +
-Общий вид ''​MID$''​ — функции следующий:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-MID$(α,​m[,​n]) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где:  +
-  * ''​MID''​ ("​MIDdle"​ — "​середина"​) — служебное слово;​ +
-  * α — строковое выражение;​ +
-  * m, n — арифметические выражения,​ целые части значений которых должны принадлежать отрезку [1,255]. +
-Напомним,​ что квадратные скобки,​ встречающиеся при описании синтаксиса,​ — обозначение,​ указывающее,​ что элемент синтаксической конструкции внутри них не является обязательным. +
- +
-Условимся целые части значений арифметических выражений m и n обозначать соответственно M и N. +
- +
-По умолчанию N равно количеству символов значения строкового выражения α от позиции M и до конца строки включительно. +
- +
-Рассмотрим два возможных случая. +
-  - <​WRAP>​ Функция ''​MID$''​ //​слева//​ от знака равенства в операторе присваивания ''​LET''​. +
-<​code>​ +
-[LET] MID$(α,​m[,​n]) = β +
-</​code>​ +
-Здесь β — строковое выражение. +
- +
-Пусть L — длина значения строкового выражения β. При выполнении оператора ''​LET''​ символы значения строкового выражения α, начиная с позиции M, последовательно замещаются на первые ''​min(L,​N)''​ +
-символов строкового выражения β. Остальные символы значения строкового выражения α остаются без изменений (см. [[#​pict_04_01|рис.1]]). +
- +
-{{anchor:​pict_04_01}} +
-<​code>​ +
-    1–й ​    ​2–й ​        ​М–й ​ (М+1)–й ​   (M+N-1)–й ​   LEN(α)–й +
-  символ ​ символ ​     символ ​ символ ​     символ ​     символ +
-    │       ​│ ​          ​│ ​      ​│ ​          ​│ ​          │ +
-┌───▼───┬───▼───┬───┬───▼───┬───▼───┬───┬───▼───┬───┬───▼───┐ +
-│       ​│ ​      │ … │███████│███████│ … │███████│ … │       │ α +
-└───────┴───────┴───┴───────┴───────┴───┴───────┴───┴───────┘ +
-                    │◀─────── N символов ──────▶│ +
-                    ▲                           ​▲ ​    +
-                    │                           │ +
-                    ┌───────────────────────────┐ +
-                    │       ​MID$(α,​M,​N) = β     │ +
-                    ▲───────────────────────────▲ +
-                    │                           │ +
-                    ┌────────────────────────────────────────┐ +
-       L > N        │███████│███████│ … │███████│ ​ … │███████│ β +
-                    └────────────────────────────────────────┘ +
-                    │◀──────────────── L символов ──────────▶│ +
-        или ​        ​▲ ​                  ▲ +
-                    │                   │ +
-                    ┌───────────────────┐─ ─ ─ ─┐ +
-       L < N        │███████│ … │███████│ ​      ​│β +
-                    └───────────────────┘─ ─▲─ ─┘ +
-                    │◀─── L символов───▶│ ​  │ +
-                                      символы из α +
-</​code>​ __//Рис. 1//__ +
- +
-{{anchor:​e0421-01}} __//​Пример//​__. +
-\\ {{.examples:​0421-01.bas|}} \\ [[+tab|wmsxbpge>​0421-01.bas]] +
-<​code>​ +
-10 X$="​12345678910":​INPUT Y$,​M,​N:​MID$(X$,​M,​N)=Y$:​PRINT X$ +
- +
-run         ​┌────────────────┐ +
-? стол,​8,​4 ​ │X$="​12345678910"​│ +
-1234567стол │           ​└──┘ │ +
-Ok          │       ​Y$="​стол"​│ +
-            └────────────────┘ +
-run         ​┌────────────────┐ +
-? сто,​8,​3 ​  ​│X$="​12345678910"​│ +
-1234567сто0 │           ​└─┘ ​ │ +
-Ok          │       ​Y$="​сто"​ │ +
-            └────────────────┘ +
- +
-run         ​┌────────────────┐ +
-? стул,​1,​4 ​ │X$="​12345678910"​│ +
-стул5678910 │    └──┘ ​       │ +
-Ок          │Y$="​стул" ​      │ +
-            └────────────────┘ +
-                   +
-run         ​┌────────────────┐ +
-? казак,​8,​5 │X$="​12345678910"​│ +
-1234567каза │           ​└──┘ │ +
-Ok          │       ​Y$="​каза"​│ +
-            └────────────────┘ +
-</​code>​ +
-И наконец,​ вместо оператора присваивания вида: +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-А$ = строковое выражение +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-используйте оператор:​ ''​MID$(А$,​1)''​ = строковое выражение,​ чтобы избежать использования дополнительной памяти. Но учтите,​ что строковая переменная A$ уже должна существовать и ''​LEN(A$)≥LEN''​ (строковое выражение)! +
-</​WRAP>​ +
-  - <​WRAP>​ Функция ''​MID$''​ //​справа//​ от знака равенства в операторе присваивания ''​LET''​. +
-<​code>​ +
-[LET] γ = MID$(α,​m[,​n]) +
-</​code>​ +
-Здесь γ — строковая переменная. +
- +
-При выполнении указанной конструкции N последовательных символов значения α, начиная с позиции M, становятся значением строковой переменной γ. Предварительное определение γ не обязательно (см. [[#​pict_04_02|рис.2]]). +
- +
-{{anchor:​pict_04_02}} +
-<​code>​ +
-    1–й ​    ​2–й ​        ​М–й ​  ​(М+1)–й ​  ​(М+N-1)–й ​   LEN(α)–й +
-  символ ​ символ ​     символ ​ символ ​     символ ​     символ +
-    │       ​│ ​          ​│ ​      ​│ ​          ​│ ​          │ +
-┌───▼───┬───▼───┬───┬───▼───┬───▼───┬───┬───▼───┬───┬───▼───┐ +
-│       ​│ ​      │ … │███████│███████│ … │███████│ … │       │ α +
-└───────┴───────┴───┴───────┴───────┴───┴───────┴───┴───────┘ +
-                    │    ┌─────────────────┐ ​   │ +
-                    │    │ γ = MID$(α,​M,​N) │    │ +
-                    │    └─────────────────┘ ​   │ +
-                    ▼───────┬───────┬───┬───────▼ +
-                    │███████│███████│ … │███████│ γ +
-                    └───────┴───────┴───┴───────┘ +
-                    │◀────── N символов────────▶│ +
-</​code>​ __//Рис. 2//__ +
- +
-__//​Примеры//​__:​ +
-  * 1) <​code>​ +
-Ok +
-? MID$("​КЛАВИАТУРА",​3,​4) +
-АВИА ​     └──┘ +
-Ok +
-</​code>​ +
-  * 2) <​code>​ +
-Ok +
-? MID$("​капрал"​+"​литр",​4,​5) +
-ралли ​     └──────┘ +
-Ok +
-</​code>​ +
-  * 3) <​code>​ +
-Ok +
-? MID$("​молоко"​+"​брат",​5,​5) +
-кобра ​      ​└──────┘ +
-Ok +
-</​code>​ +
-  * 4) <​code>​ +
-Ok           +
-? MID$("​СОР У НОР",​3,​5) +
-Р У Н     ​└───┘ +
-Ok +
-</​code>​ +
-  * 5) <​code>​ +
-Ok +
-10 input I,J:? MID$("​234",​I,​J) ​      +
-run    run     ​run ​    ​run ​          +
-? 1,1  ? 2,90  ? 10,1  ? 1,0         +
-2      34                            +
-Ok     ​Ok ​     Ok      Ok            +
- +
-run       ​или ​    ​run ​               +
-? -1,1            ? 0,0              +
-Illegal function call in 10          +
-Ok                                   +
- +
-run       ​или ​    ​run ​               +
-? 2,-1            ? 0,1 +
-Illegal function call in 10          +
-Ok +
-</​code>​ +
-  * {{anchor:​e0421-06}} 6) +
-{{.examples:​0421-06.bas|}} \\ [[+tab|wmsxbpge>​0421-06.bas]] +
-<​code>​ +
-NEW +
-Ok +
-1 Z$="​123"​ +
-2 INPUT X$,M +
-3 Z$=MID$(X$,​M) +
-4 Y$=MID$(X$,​M+4) +
-5 PRINT Z$ +
-6 PRINT Y$ +
-run +
-? Баба-Яга-костяная нога,​6 +
-Яга-костяная нога +
-костяная нога +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e0421-07}} <​WRAP>​ 7) определить третий символ в слове X$. <​code>​ +
-Ok +
-input x$:​z$=mid$(x$,​3,​1):​print z$ +
-? интеграл +
-т +
-Ok +
-</​code>​ +
- +
-Если требуется определить K–й символ в слове X$, то программа будет иметь следующий вид (разумеется,​ ''​1≤K≤LEN(X$)''​):​ +
-\\ {{.examples:​0421-07.bas|}} \\ [[+tab|wmsxbpge>​0421-07.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT X$,K +
-20 IF K<1 OR K>​LEN(X$) THEN PRINT"​Буквы с указанным номером в слове нет":​END ELSE Z$=MID$(X$,​K,​1):​PRINT Z$:END +
-run +
-? информатика,​3 +
-ф +
-Оk +
- +
-run +
-? информатика,​12 +
-Буквы с указанным номером в слове нет +
-Ok +
-</​code>​ +
-</​WRAP>​ +
- +
-__//​Пример 8//__. Для получения числа, состоящего из двух младших цифр целого числа N, воспользуйтесь строкой:​ +
-<​code>​ +
-10 X%=VAL(MID$(STR$(N),​LEN(STR$(N))-1,​2)) +
-</​code>​ +
-Заметим,​ что Вы можете выполнить то же самое, используя функцию ''​INT()'':​ +
-<​code>​ +
-10 INPUT N:PRINT N-INT(N/​100)*100 +
-</​code>​ +
- +
-{{anchor:​e0421-09}} __//​Пример 9//__. Написать программу,​ определяющую,​ сколько раз слово Z$ встречается в слове X$. +
-\\ {{.examples:​0421-09.bas|}} \\ [[+tab|wmsxbpge>​0421-09.bas]] +
-<​code>​ +
-NEW +
-Оk +
-10 INPUT X$,Z$:J=0 +
-20 FOR I=1 TO LEN(X$)-LEN(Z$)+1 +
-30 IF Z$<>​MID$(X$,​I,​LEN(Z$)) THEN NEXTI ELSE J=J+1:​NEXTI +
-40 PRINT J:END +
-run +
-? БАОБАБ,​БА +
- 2 +
-Ok +
-</​code>​ +
- +
- +
-{{anchor:​e0421-10}} __//​Пример 10//__. Написать программу,​ заменяющую в слове X$ слово Z$ на слово Y$ той же длины. +
-\\ {{.examples:​0421-10.bas|}} \\ [[+tab|wmsxbpge>​0421-10.bas]] +
-<​code>​ +
-NEW +
-Оk +
-10 INPUT X$,Z$,Y$:IF LEN(Z$)><​LEN(Y$) THEN 10 +
-20 FOR J=1 TO LEN(X$)-LEN(Z$)+1 +
-30 IF Z$<>​MID$(X$,​J,​LEN(Z$)) THEN 50 +
-40 MID$(X$,​J,​LEN(Y$))=Y$ +
-50 NEXT J:PRINT X$:END +
-run +
-? ДОМ КИРПИЧНЫЙ +
-?? КИРПИЧНЫЙ +
-?? БАНАНОВЫЙ +
-ДОМ БАНАНОВЫЙ +
-Оk +
-</​code>​ +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Косо лети же, житель осок. +
-<WRAP rightalign>​ +
-—//​В.Хлебников//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Я разуму уму заря,​\\ +
-Я иду с мечом судия. +
-<WRAP rightalign>​ +
-—//​Г.Р.Державин//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Мечтатель! Летать чем? +
-<WRAP rightalign>​ +
-—//​С.Кирсанов//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-{{anchor:​e0421-10}} __//​Пример 11//__. Слова и фразы, переходящие в себя при "​акустическом отображении",​ получили название //​палиндромов//​. Это слово греческого происхождения и означает "​движущийся обратно",​ "​обратимый"​. Найти палиндром практически невозможно,​ но его нетрудно построить. В качестве "​строительных блоков"​ простейших палиндромов следует выбирать слова, не изменяющиеся при чтении от конца к началу. Выдерживают ​ отражение в "​акустическом зеркале"​ такие слова, как боб, дед, кок, мим, иди, топот, потоп, колок, ротор, кабак, моном и выражения,​ такие, например,​как "​Лёша на полке клопа нашёл"​. +
-\\ {{.examples:​0421-11.bas|}} \\ [[+tab|wmsxbpge>​0421-11.bas]] +
-<​code>​ +
-Ok +
-10 INPUT X$:​Y$=""​ +
-20 FOR I=1 TO LEN(X$):​Y$=MID$(X$,​I,​1)+Y$:​NEXT +
-30 IF X$=Y$ THEN PRINT"​Палиндром!"​ ELSE PRINT"​Не палиндром!"​ +
-run +
-? косолетижежителосок +
-Палиндром! +
-Ok +
- +
-run +
-? мечтателлетатчем +
-Палиндром! +
-Ok                      +
- +
-run +
-? я разуму уму заря +
-Не палиндром! +
-Ok +
-</​code>​ +
-Сравните результат действия функции ''​MID$(A$,​I,​J)'',​ стоящей справа от знака равенства в операторе присваивания,​ с результатом операции //​вырезки//:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-A[i:​i+j-1] +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * А — текст;​ +
-  * i — номер первого символа фрагмента,​ вырезаемого из текста A; +
-  * j — количество символов в фрагменте,​ вырезаемом из текста A, +
-в школьном алгоритмическом языке. +
- +
-Рассмотрите интересный часто встречающийся частный случай j=1, т.е. проведите аналогию между ''​MID$(A$,​I,​1)''​ и ''​A[i:​i]''​. +
- +
-И, наконец,​ сопоставьте результат действия функции ''​MID$'',​ стоящей слева от знака равенства в операторе присваивания,​ с результатом работы команды частичного изменения значения литерной величины (команды присваивания вырезке) +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-A[i:j]=B +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-позволяющей заменить часть слова А, начинающуюся с i–той буквы и оканчивающуюся j–той буквой,​ на слово B, в школьном алгоритмическом языке. +
- +
-{{anchor:​left}} +
-==== IV.2.2. LEFT$–функция ==== +
- +
-Общий вид функции:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-LEFT$(α,​n) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​LEFT''​ ("​left"​ — "​левый"​) — служебное слово;​ +
-  * α — строковое выражение;​ +
-  * n — арифметическое выражение,​ целая часть значения которого должна принадлежать отрезку [0,255]. +
- +
-Функция ''​LEFT$''​ позволяет выделить самые //​левые//​ n символов значения строкового выражения α. +
- +
-''​LEFT$''​ — функция является "​частным случаем"​ ''​MID$''​–функции и через неё может быть определена так: +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-LEFT$(α,n) = MID$(α,​1,​n) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-__//​Примеры//​__:​ +
-  * {{anchor:​e0422-01}} <​WRAP>​ 1) +
-\\ {{.examples:​0422-01.bas|}} \\ [[+tab|wmsxbpge>​0422-01.bas]] +
-<​code>​ +
-Ok +
-10 INPUT X$,N +
-20 U$=MID$(X$,​1,​N) +
-30 V$=LEFT$(X$,​N) +
-40 PRINT U$;V$ +
-run +
-? 1234567890,​6 +
-123456123456 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * 2)<​code>​ +
-Ok +
-? LEFT$("​деньги",​0) +
-Illegal function call +
-Ok +
-</​code>​ +
-  * 3) <​code>​ +
-Ok +
-? LEFT$("​деньги",​4) +
-день ​    ​└──┘ +
-Ok +
-</​code>​ +
-  * 4) <​code>​ +
-Ok +
-? LEFT$("​abc",​2);​LEFT$(LEFT$("​def",​2),​1) +
-abd +
-Ok +
-</​code>​ +
-  * 5) <​code>​ +
-Ok  +
-? LEFT$("​wap",​-1) +
-Illegal function call +
-Ok       +
-</​code>​ +
- +
-{{anchor:​right}} +
-==== IV.2.3. RIGHT$–функция ==== +
- +
-Общий вид функции:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-RIGHT$(α,​n) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где:  +
-  * ''​RIGHT''​ ("​right"​ — "​правый"​) — служебное слово;​ +
-  * α — строковое выражение;​ +
-  * n — арифметическое выражение,​ целая часть значения которого должна принадлежать отрезку [0,255]. +
-Функция ''​RIGHT$''​ позволяет выделить самые //​правые//​ n символов значения строкового выражения α (в этом смысле функция ''​RIGHT$()''​ симметрична функции ''​LEFT$()''​!). +
- +
-''​RIGHT$''​ — функция является частным случаем ''​MID$''​–функции и через неё может быть определена так: +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-RIGHT$(α,​n) = MID$(α,​L-n+1,​n) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где L — длина значения строкового выражения α. +
- +
-__//​Примеры//​__:​ +
-  * 1) <​code>​ +
-Ok +
-? RIGHT$("​abcdgoldfish",​8) +
-goldfish ​     └──────┘ +
-Ok +
-</​code>​ +
-  * 2) <​code>​ +
-Ok +
-? RIGHT$("​гамбит",​3) +
-бит ​         └─┘ +
-Ok +
-</​code>​ +
-  * {{anchor:​e0423-03}} <​WRAP>​ 3) +
-\\ {{.examples:​0423-03.bas|}} \\ [[+tab|wmsxbpge>​0423-03.bas]] +
-<​code>​ +
-Ok +
-10 INPUT X$,N +
-20 U$=MID$(X$,​LEN(X$)-N+1) +
-30 V$=RIGHT$(X$,​N):?​ U$;V$ +
-run +
-? 1234567890,​4 +
-78907890 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * 4) <​code>​ +
-Ok +
-? RIGHT$(LEFT$("​рубaйте!",​6),​4) +
-байт +
-Ok +
-</​code>​ +
-  * 5)<​code>​ +
-Ok +
-? MID$("​рубайте!",​3,​4) ​    +
-байт ​     └──┘ ​         +
-Ok +
-</​code>​ +
-Заметим,​ что хотя функции ''​LEFT$''​ и ''​RIGHT$''​ являются "​частными случаями"​ функции ''​MID$'',​ их нельзя использовать //​слева//​ от символа присваивания в операторе ''​LET''​! +
- +
-Посмотрите… +
-<​code>​ +
-NEW +
-Ok +
-1 A$="​Барсик":​MID$(A$,​1,​4)="​Корт":​PRINT A$ +
-2 B$="​Комик":​LEFT$(B$,​3)="​Том":​PRINT B$ +
-run +
-Кортик +
-Syntax error in 2 +
-Ok +
-</​code>​ +
- +
-{{anchor:​e0423-06}} __//​Пример 6//__. Образовать слово Y$, состоящее из первых N и последних К символов данного слова Х$. +
-\\ {{.examples:​0423-061.bas|}} \\ [[+tab|wmsxbpge>​0423-061.bas]] +
-Первоначальный вариант программы выглядит так: +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT X$,N,K +
-20 Y$=LEFT$(X$,​N)+RIGHT$(X$,​K) +
-30 PRINT "​Результат:";​Y$ +
-40 END +
-run +
-? аллигатор,​3,​6 +
-Результат:​аллигатор +
-Ok +
- +
-run +
-? аллигатор,​0,​6 +
-Результат:​игатор +
-Ok +
- +
-run +
-? аллигатор,​0,​0 +
-Результат:​ +
-Ok +
- +
-однако… +
- +
-run +
-? аллигатор,​-4,​3 +
-Illegal function call in 20 +
-Ok +
-</​code>​ +
-Поэтому дополним программу строкой:​ +
-\\ {{.examples:​0423-062.bas|}} \\ [[+tab|wmsxbpge>​0423-062.bas]] +
-<​code>​ +
-15 IF N<0 OR N>​LEN(X$) OR K<0 OR K>​LEN(X$) THEN PRINT"​Не балуйтесь! Повторите!":​GOTO 10 +
-</​code>​ +
-Выполним полученную программу:​ +
-<​code>​ +
-run +
-? аллигатор,​9,​10 +
-Не балуйтесь! Повторите! +
-? аллигатор,​6,​0 +
-Результат:​аллига +
-Оk +
- +
-run +
-? аллигатор,​-1,​5 +
-Не балуйтесь! Повторите! +
-? аллигатор,​9,​10 +
-Не балуйтесь! Повторите! +
-+
-</​code>​ +
-Строка 15 обеспечивает повторный запрос на ввод исходных данных в том случае,​ когда K<0 или К> длины слова Х$, или N<0, или N>​длины слова X$ (своеобразная "​защита"​ программы от непредусмотренной исходной информации). +
- +
-{{anchor:​e0423-07}} __//​Пример 7//__. Написать программу перевода чисел, записанных римскими цифрами,​ в числа, записанные арабскими цифрами. +
-\\ {{.examples:​0423-07.bas|}} \\ [[+tab|wmsxbpge>​0423-07.bas]] +
-<​code>​ +
-NEW +
-Ok +
-1 DATA 1000,​M,​900,​CM,​500,​D,​400,​CD,​100,​C,​90,​XC,​50,​L,​40,​XL,​10,​X,​9,​IX,​5,​V,​4,​IV,​1,​I:​INPUT"​N$";​N$ +
-2 READ A,A$ +
-3 IF A$=LEFT$(N$,​LEN(A$)) THEN N$=RIGHT$(N$,​LEN(N$)-LEN(A$)):​N=N+A:​GOTO 3 +
-4 IF N$>"​ "GOTO 2 +
-5 PRINT N +
-run +
-N$? IV +
- ​4 ​          +
-Ok +
- +
-run +
-N$? CMIV +
- 904 +
-Ok +
- +
-run +
-N$? MMMDXCLLI +
- ​3691 +
-Ok +
- +
-run +
-N$? MCMXVII +
- ​1917 +
-Ok +
- +
-run +
-N$? MDCCCXII +
- ​1812 +
-Ok +
-</​code>​ +
-А как насчёт программы обратного перевода?​ Пожалуйста! +
- +
-{{anchor:​e0423-08}} __//​Пример 8//__. Написать программу перевода чисел, записанных арабскими цифрами,​ в числа, записанные римскими цифрами. +
-\\ {{.examples:​0423-08.bas|}} \\ [[+tab|wmsxbpge>​0423-08.bas]] +
-<​code>​ +
-NEW +
-Ok +
-1 DATA 1000,​M,​900,​CM,​500,​D,​400,​CD,​100,​C,​90,​XC,​50,​L,​40,​XL,​10,​X,​9,​IX,​5,​V,​4,​IV,​1,​I:​INPUT"​N";​N +
-2 READ A,A$ +
-3 IF A<=N THEN PRINT A$;:​N=N-A:​GOTO 3 +
-4 IF N>0 GOTO 2 +
-run +
-N? 654 +
-DCLIV +
-Ok +
- +
-run +
-N? 25 +
-XXV +
-Ok +
- +
-run +
-N? 11111 +
-MMMMMMMMMMMCXI +
-Ok                 +
- +
-run +
-N?3691 +
-MMMDCXCI +
-Ok +
-</​code>​ +
- +
-{{anchor:​string}} +
-==== IV.2.4. STRING$–функция ==== +
- +
-Общий вид STRING$ — функции следующий:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-STRING$(n,​α) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-или +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-STRING$(n,​m) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где:  +
-  * ''​STRING''​ ("​string"​ — "​строка"​) — служебное слово;​ +
-  * α — строковое выражение;​ +
-  * n,m — арифметические выражения,​ целые части значений которых должны принадлежать отрезку [0,255]. +
- +
-Обозначим N—значение арифметического выражения n. Тогда, в случае формата ''​STRING$(n,​α)''​ функция возвращает строку,​ состоящую из N одинаковых символов,​ равных первому символу значения строкового выражения α. А в случае формата ''​STRING$(n,​m)''​ значением функции является последовательность N одинаковых символов,​ код ASCII которых одинаков (ведь символы одинаковы!) и равен целой части значения арифметического выражения m. +
- +
-Поэтому,​ если Вы хотите инициализировать строковую переменную A$, N //​пробелами//​ (наиболее часто встречающаяся операция!),​ то два приведённых ниже оператора выполняют идентичное действие:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-A$=STRING$(N,​32) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-A$=STRING$(N,"​ ") +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-(ведь ''​CHR$(32)=%%"​ "​%%''​ !). +
-</​WRAP>​ +
-</​WRAP>​ +
- +
- +
-Таким образом,​ с помощью ''​STRING$''​–функции можно назначать длину и проводить инициализацию строковых переменных пробелами. Приведём несколько тривиальных примеров:​ +
-  * 1) <​code>​ +
-Ok +
-Y$=STRING$(10,"​*"​):?​ LEN(Y$):? "#"​+Y$+"​FILE"​ +
- 10 +
-#​**********FILE +
-Ok +
-</​code>​ +
-  * 2) <​code>​ +
-Ok +
-print STRING$(10,​52);​STRING$(10,​CHR$(52)) +
-44444444444444444444 +
-Ok +
-</​code>​ +
-  * 3) <​code>​ +
-Ok +
-A$=STRING$(5,"​ "​):​MID$(A$,​3,​3)="​Все!":?​ A$ +
-··Все +
-Ok +
-</​code>​ +
-Если n=0, то функция ''​STRING$''​ возвращает пустую строку (%%""​%%),​ независимо от того, какие α или m Вы задали. +
- +
-В тех случаях,​ когда целые части значений арифметических выражений n и m находятся вне отрезка [0,255], на экране дисплея появляется сообщение об ошибке:​ +
-<WRAP centeralign>"​Illegal function call" \\ (//"​Недопустимый вызов функции"//​).</​WRAP>​ +
- +
-{{anchor:​space}} +
-==== IV.2.5. SPACE$–функция ==== +
- +
-Общий вид функции:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-SPACE$(n) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​SPACE''​ ("​space"​ — "​пространство"​) — служебное слово;​ +
-  * n — арифметическое выражение,​ целая часть значения которого должна принадлежать отрезку [0,255]. +
-С помощью ''​SPACE$''​–функции назначается длина и проводится начальная инициализация пробелами строковых переменных. Например,​ если Вы хотите инициализировать новую строковую переменную X$ N пробелами,​ то используйте оператор присваивания ''​X$=SPACE$(N)''​ +
- +
-''​SPACE$''​–функция является частным случаем ''​STRING$''​–функции и через неё может быть определена так: +
-  SPACE$(n)=STRING$(n,"​ ") +
- +
-==== IV.2.6. Примеры ==== +
- +
-  * {{anchor:​e0426-01}} <​WRAP>​ 1) выделить из текста,​ являющегося значением строковой переменной T$, отдельные слова (они отделены друг от друга одним пробелом) и записать их в строковый массив с именем W$. (Психологи утверждают,​ что из минуты,​ затраченной на чтение,​ мы 58 секунд считываем промежутки между символами!) +
-\\ {{.examples:​0426-01.bas|}} \\ [[+tab|wmsxbpge>​0426-01.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 LINEINPUT T$:​T$=T$+"​ ":​K=0'​K-количество слов в T$ +
-20 FOR I=1 TO LEN(T$):IF MID$(T$,​I,​1)="​ " THEN K=K+1 +
-35 NEXT I '​Количество слов в Т$ найдено! +
-40 DIM W$(K):DIM P(K)'​Вот теперь можно описать массивы! +
-45 FOR J=1 TO K:​W$(J)=SPACE$(5):​NEXTJ '​Начальная инициализация пробела ми элементов массива W$(K) +
-47 N=1:FOR J=1 TO K:FOR I=N TO LEN(T$) +
-70 IF MID$(T$,​I,​1)="​ " GOTO 85 +
-80 NEXT I +
-85 P(J)=I:​W$(J-1)=MID$(T$,​N,​P(J)-P(J-1)-1):​N=P(J)+1:​PRINT W$(J-1);​SPC(5) +
-90 NEXT J +
-run +
-123 4 567 +
-123·····4·····567 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Елечвок енмяет ослог. +
-<WRAP rightalign>​ +
-—//​А.Вознесенский. Человек//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-  * {{anchor:​e0426-02}} <​WRAP>​ 2) даны два слова X$ и Y$. Проверить,​ можно ли из символов,​ входящих в слово X$, составить слово Y$. Символы можно переставлять,​ и каждый символ можно использовать несколько раз! +
-\\ {{.examples:​0426-02.bas|}} \\ [[+tab|wmsxbpge>​0426-02.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT X$,Y$ +
-30 FOR I=1 TO LEN(Y$):FOR J=1 TO LEN(X$) +
-50 IF MID$(Y$,​I,​1)=MID$(X$,​J,​1) THEN A$="​да":​NEXT I ELSE A$="​нет":​NEXT J +
-80 PRINT A$:END +
-run                  run +
-? школаа,​алокша ​     ? AB,BB +
-да                   ​да +
-Ok                   Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e0426-03}} <​WRAP>​ 3) даны два натуральных числа M и N. Проверьте,​можно ли из цифр числа M составить число N. Цифры можно переставлять и использовать:​ +
-  * <​WRAP>​ a) более одного раза  +
-\\ {{.examples:​0426-031.bas|}} \\ [[+tab|wmsxbpge>​0426-031.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT M,​N:​M$=STR$(M):​N$=STR$(N) +
-30 FOR I=2 TO LEN(N$):FOR J=2 TO LEN(M$) +
-40 IF MID$(N$,​I,​1)<>​MID$(M$,​J,​1) THEN NEXT J:?"​Нельзя!"​ELSE NEXTI:?"​Можно!"​ +
-run              run              run +
-? 6785,​58758 ​    ? 6785,​58358 ​    ? 6785,87 +
-Можно! ​          ​Нельзя! ​         Можно! +
-Ok               ​Ok ​              Ok +
- +
-</​code>​ +
-</​WRAP>​ +
-  * <​WRAP>​b) не более одного раза  +
-\\ {{.examples:​0426-032.bas|}} \\ [[+tab|wmsxbpge>​0426-032.bas]] +
-<​code>​ +
-b) +
-NEW +
-Ok +
-10 INPUT M,​N:​X$="​ ":​M$=STR$(M):​N$=STR$(N) +
-40 FOR I=2 TO LEN(N$):FOR J=2 TO LEN(M$) +
-50 IF MID$(N$,​I,​1)=MID$(M$,​J,​1) THEN MID$(N$,​I,​1)=X$:​MID$(M$,​J,​1)=X$:​NEXTI:?"​Можно!"​ ELSE NEXTJ:?"​Нельзя!"​ +
-run                    run +
-? 12345432,​1236 ​       ? 1234554320,​1022 +
-Нельзя! ​               Можно! +
-Ok                     Ok +
-</​code>​ +
-</​WRAP>​ +
- +
-</​WRAP>​ +
-  * {{anchor:​e0426-04}} <​WRAP>​ 4) число 41 обладает следующим свойством:​ 41²=1681,​√16=4 и √81=9, т.е. числа 16 и 81 — точные квадраты;​ найти все натуральные числа, не превосходящие N, и такие, что первые две и последние две цифры квадрата числа являются точными квадратами. +
-\\ {{.examples:​0426-04.bas|}} \\ [[+tab|wmsxbpge>​0426-04.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT"​Сколько чисел необходимо проверить";​N:​PRINT"​Интересующие Вас числа:";​ +
-20 FOR I=10 TO N:B=I^2 +
-40 B$=MID$(STR$(B),​2):​IF VAL(RIGHT$(B$,​2))<>​0 THEN 50 ELSE NEXT I: END +
-50 IF SQR(VAL(LEFT$(B$,​2)))=FIX(SQR(VAL(LEFT$(B$,​2)))) AND SQR(VAL(RIGHT$(B$,​2)))=FIX(SQR(VAL(RIGHT$(B$,​2))))THENPRINT I;:NEXTI ELSE NEXTI +
-run +
-Сколько чисел необходимо проверить?​ 100 +
-Интересующие Вас числа: 41 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e0426-05}} <​WRAP>​ 5) написать программу,​ которая заменяет часть слова Z$ текста T$ на текст Y$ с сохранением одного пробела между словами. +
-\\ {{.examples:​0426-05.bas|}} \\ [[+tab|wmsxbpge>​0426-05.bas]] +
-<​code>​ +
-NEW +
-Ok +
-5 PRINTSPC(8);"​Вводите текст !":​LINEINPUT T$:​T$=T$+"​ ":​K=0 +
-15 INPUT "​Какое слово менять";​Z$ +
-16 INPUT "На какое слово менять";​Y$ +
-20 FOR I=1 TO LEN(T$):IF MID$(T$,​I,​1)="​ " THEN K=K+1:NEXTI ELSE NEXTI '​K-количество слов в тексте T$ +
-40 DIM W$(K):DIM P(K)'​Вот теперь можно описать массивы! +
-45 FOR J=1 TO K:​W$(J)=SPACE$(5):​NEXT J +
-47 N=1'​N-номер первой буквы текущего слова в тексте +
-50 FOR J=1 TO K: FOR I=N TO LEN(T$) +
-70 IF MID$(T$,​I,​1)="​ " GOTO 85 +
-80 NEXT I +
-84 '​P()-массив,​содержащий номера позиций пробелов в тексте +
-85 P(J)=I:​W$(J-1)=MID$(T$,​N,​P(J)-P(J-1)-1):​N=P(J)+1 +
-90 NEXT J +
-95 A$="​Образец не найден! Ваш текст:"​ +
-100 FOR J=0 TO K-1 +
-105 IF W$(J)=Z$ THEN W$(J)=Y$:​A$="":​GOTO 120 +
-106 FOR I=1 TO LEN(W$(J))-LEN(Z$)+1 +
-107 IF Z$<>​MID$(W$(J),​I,​LEN(Z$))THEN115 +
-108 W$(J)=LEFT$(W$(J),​I-1)+Y$+RIGHT$(W$(J),​LEN(W$(J))-I-LEN(Z$)+1):​A$=""​ +
-115 NEXTI +
-120 NEXT J +
-130 FOR J=0 TO K-1:​B$=B$+W$(J)+"​ ":​NEXT +
-145 PRINT A$ +
-150 PRINT B$:END +
-run +
-········Вводите текст ! +
-Мама мыла Эмму +
-Какое слово менять?​ мы +
-На какое слово менять?​ очень люби +
-································· +
-Мама очень любила Эмму +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e0426-06}} <​WRAP>​ 6) составьте программу,​ в результате работы которой выяснялось бы, можно ли переставить цифры десятичной записи числа K так, чтобы они образовывали арифметическую или геометрическую прогрессию. +
-\\ {{.examples:​0426-06.bas|}} \\ [[+tab|wmsxbpge>​0426-06.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 CLS:DIM K,​M%,​D%,​Q,​F$:​INPUT"​Введите нат. число";​K +
-30 F$=STR$(K):​M%=LEN(F$):​DIM A(M%) +
-40 FOR I=1 TO M%:​A(I)=VAL(MID$(F$,​I,​1)):​NEXT +
-50 FOR I=2 TO M%-1:FOR J=I+1 TO M% +
-60 IF A(I)>​A(J)THEN SWAP A(I),A(J) +
-70 NEXT J,I +
-80  D%=A(3)-A(2) +
-90 IF M%<3 THEN PRINT"​Число должно содержать не менее 2 цифр":​GOTO 20 +
-100 IF M%=3 THEN PRINT"​Арифм.прогрессия есть!":​GOTO 150 +
-110 FOR I=4TO M% +
-120 IF A(I)-A(I-1)<>​D%THEN ?"​Арифм.прогрессии нет":​GOTO160 +
-130 NEXT I +
-140 PRINT"​Арифм.прогрессия есть!"​ +
-150 IF M%=3 AND A(3)=0 THEN PRINT"​Геом.прогрессии нет":​END +
-160 FOR I=2 TO M%:IF A(I)=0 THEN?"​Геом.прогрессии нет":​END +
-170 NEXT I +
-180 Q=A(3)/​A(2) +
-190 IF M%=3 THEN ?"​Геом.прогрессия есть!":​END +
-200 FOR I=4 TO M% +
-210 IF A(I)/​A(I-1)<>​Q THEN PRINT"​Геом.прогрессии нет":​END +
-220 NEXT I +
-230 PRINT"​Геом.прогрессия есть!":​END +
-run                             run +
-Введите нат. число? 7132546 ​    ​Введите нат. число? 42 +
-Арифм.прогрессия есть! ​         Арифм.прогрессия есть! +
-Геом.прогрессии нет ​            ​Геом.прогрессия есть! +
-Ok                              Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e0426-07}} <​WRAP>​ 7) составить программу,​ которая m–кратно повторяет каждый символ в слове X$. +
-\\ {{.examples:​0426-07.bas|}} \\ [[+tab|wmsxbpge>​0426-07.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT"​Введите слово";​X$ +
-20 INPUT"​Укажите число повторений символов";​M% +
-30 IF M%=0 OR M%*LEN(X$)>​255 THEN ?"​Повторите ввод":​GOTO10 +
-40 N$="":​FOR I=1 TO LEN(X$):FOR J=1 TO M% +
-70 N$=N$+MID$(X$,​I,​1):​NEXTJ,​I +
-90 PRINT "Вы этого хотели? ​ ";N$ +
-run +
-Введите слово? керпкпр +
-Укажите число повторений символов?​ 2 +
-Вы этого хотели? ​ ккееррппккппрр +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e0426-08}} <​WRAP>​ 8) составить программу вывода всех натуральных чисел, меньших N, сумма квадратов цифр которых равна M. +
-\\ {{.examples:​0426-08.bas|}} \\ [[+tab|wmsxbpge>​0426-08.bas]] +
-<​code>​ +
-NEW +
-Ok +
-5 DEFINT I,​J,​N,​M,​Y:​INPUT N,M +
-10 FOR I=1 TO N:​Y=0:​A$=STR$(I) +
-20 FOR J=2 TO LEN(A$):​Y=Y+VAL(MID$(A$,​J,​1))^2:​NEXTJ +
-30 IF Y=M THEN PRINTI;:​NEXTI ELSE NEXTI +
-40 END +
-run +
-? 123,65 +
-·18··47··74··81··108 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e0426-09}} <​WRAP>​ 9) по данному натуральному N найдите наименьшее из чисел, имеющих столько же и таких же цифр, что и N, если известно,​ что каждую цифру числа N можно использовать при записи один раз. +
-\\ {{.examples:​0426-09.bas|}} \\ [[+tab|wmsxbpge>​0426-09.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 DEFINT I,J: DEFSTR A +
-20 INPUT "В каком числе хотите перетрясти цифры";​N +
-25 IF LEN(STR$(N))>​14 THEN PRINT "Не озоруй!":​GOTO 20 +
-30 FOR I=0 TO9:FOR J=2 TO LEN(STR$(N)) +
-40 IF I=VAL(MID$(STR$(N),​J,​1))THEN A=A+STR$(I) +
-50 NEXT J,I +
-60 PRINT VAL(A):​END +
-run +
-В каком числе хотите перетрясти цифры? 87655543 +
-·34555678 +
-Ok +
-run +
-В каком числе хотите перетрясти цифры? 112235799435213 +
-Не озоруй! +
-В каком числе хотите перетрясти цифры? … +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e0426-10}} <​WRAP>​ 10) написать программу,​ устанавливающую,​ какие из натуральных чисел, небольшие заданного натурального M, делятся на каждую свою цифру. +
-\\ {{.examples:​0426-10.bas|}} \\ [[+tab|wmsxbpge>​0426-10.bas]] +
-<​code>​ +
-10 DEFINT I,​J,​M:​DEFSTR A:INPUT M +
-30 FOR I=1 TO M:​A=STR$(I):​FOR J=2 TO LEN(A) +
-55 IF VAL(MID$(A,​J,​1))=0 THEN NEXT J:NEXT I:END ELSE::::IF I MOD VAL(MID$(A,​J,​1))=0 THEN NEXTJ:​PRINTI;:​NEXTI ELSE NEXTI +
-run +
-? 40 +
-·1··2··3··4··5··6··7··8··9··11··12··15··22··24··33··36 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e0426-11}} <​WRAP>​ 11) определите,​ сколько цифр используется в записи натурального числа X только по одному разу. +
-\\ {{.examples:​0426-111.bas|}} \\ [[+tab|wmsxbpge>​0426-111.bas]] +
-\\ Первый способ. +
-<​code>​ +
-10 INPUT X:​X$=STR$(X) +
-20 K=0 +
-30 FOR J=2 TO LEN(X$) +
-40 P=0 +
-50 FOR I=2 TO LEN(X$) +
-60 IF MID$(X$,​J,​1)=MID$(X$,​I,​1) THEN P=P+1 +
-70 NEXTI +
-80 IF P=1 THEN K=K+1 +
-90 NEXTJ +
-100 PRINT "​K=";​K +
-run +
-? 45687345976 +
-K=3 +
-Ok +
-</​code>​ +
- +
-\\ {{.examples:​0426-112.bas|}} \\ [[+tab|wmsxbpge>​0426-112.bas]] +
-\\ Второй способ +
-<​code>​ +
-10 INPUT"​Введите число";​X$ +
-20 L=LEN(X$):​P=L +
-30 FOR I=1 TO L:FOR J=1TO L +
-40 IFMID$(X$,​I,​1)=MID$(X$,​J,​1)ANDI<>​J THEN P=P-1:NEXTI ELSE NEXT J,I +
-50 PRINT"​Цифр,​используемых 1 раз:";​P +
-run +
-Введите число? 12341524162 +
-Цифр,​используемых 1 раз: 3 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e0426-12}} <​WRAP>​ 12) из каждого слова массива C$(N) слов вычеркнуть те символы,​ которые употребляются при написании каждого из слов массива. +
-\\ {{.examples:​0426-12.bas|}} \\ [[+tab|wmsxbpge>​0426-12.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 CLEAR 1500 +
-20 INPUT"​Введите количество слов";​N:​PRINT"​Вводите слова!"​ +
-27 'В строках 30-60 идентификация исходного массива C$(N). +
-30 DIM C$(N):FOR I=1 TO N:​INPUTC$(I):​NEXT:​K$=""​ +
-75 'В строках 80-130 находятся "​общие"​ символы. Значение переменной К$ состоит из "​общих"​ символов. +
-80 FOR I=1 TO N:FOR J=1 TO LEN(C$(I)):​FOR R=1 TO N +
-110 FOR K=1 TO LEN(C$(R)) +
-120 IF MID$(C$(I),​J,​1)=MID$(C$(R),​K,​1) THEN NEXT R:​K$=K$+MID$(C$(I),​J,​1):​NEXT J ELSE NEXT K,J +
-130 NEXT I +
-135 'В строках 140-180 происходит"​вычеркивание"​из слов массива "​общих"​ символов. +
-140 FOR I=1 TO N:FOR J=1 TO LEN(C$(I)):​FOR K=1 TO LEN(K$) +
-170 IF MID$(C$(I),​J,​1)=MID$(K$,​K,​1)THENMID$(C$(I),​J,​1)="​ " +
-180 NEXT K,J,I +
-185 '​Строки 190-230 выполняют "​сжатие"​ слов массива C$(N),​т.к.при "​вычеркивании"​ "​общих"​ символов образуются пробелы. +
-190 DIM N$(N) +
-200 FOR I=1 TO N:FOR J=1 TO LEN(C$(I)) +
-220 IF MID$(C$(I),​J,​1)<>"​ "​THENN$(I)=N$(I)+MID$(C$(I),​J,​1) +
-230 NEXT J,I +
-240 FOR I=1TO N:​PRINT"​Вот";​I;"​слово:"​ ;​N$(I);" ​  - не правда ли?":​NEXT +
-run +
-Введите количество слов? 4 +
-Вводите слова! +
-? апро +
-? ажип +
-? сонп +
-? портфель +
-Вот 1 слово:​аро ​  - не правда ли? +
-Вот 2 слово:​ажи ​  - не правда ли? +
-Вот 3 слово:​сон ​  - не правда ли? +
-Вот 4 слово:​ортфель ​  - не правда ли? +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e0426-13}} <​WRAP>​ 13) определить количество //​различных//​ букв, встречающихся в слове A$ более одного раза. +
-\\ {{.examples:​0426-13.bas|}} \\ [[+tab|wmsxbpge>​0426-13.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT A$:S=0 +
-20 FOR I=1 TO LEN(A$) +
-30    P=0 +
-40    FOR J=1 TO LEN(A$) +
-50       IF MID$(A$,​I,​1)=MID$(A$,​J,​1) THEN P=P+1 +
-60    NEXT J +
-70    IF P>1 THEN S=S+1/P +
-80 NEXT I +
-90 PRINT FIX(S+.5):​END +
-run +
- ​aaaaaaaa +
- 1 +
-Ok +
- +
-run +
-? бегемот +
- 1 +
-Ok +
- +
-run +
-? Кинг-Конг +
- 3 +
-Ok +
- +
-run +
-? мяучело +
- 0 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
- +
-{{anchor:​deffn}} +
-===== IV.3. Функции пользователя. Оператор DEF FN ===== +
- +
-Язык [[msx:​basic:​]] предоставляет возможность программисту (пользователю) //​определять//​ в составляемой им программе одну или несколько "​собственных"​ функций с помощью специального оператора ''​DEF FN'',​ имеющего следующий синтаксис:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-DEF FNα[(аргумент [, аргумент] …)] = β +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​DEF FN''​ ("​FuNction DEFinition"​ — "​определение функции"​) — служебные слова;​ +
-  * α — имя переменной,​ для которой выделяется память;​ +
-  * аргумент — имя переменной,​ для которой память не выделяется (функции пользователя могут иметь не более 9 аргументов);​ +
-  * β — выражение,​ имеющее тот же тип, что и α. +
-Итак, оператор,​ определяющий функцию пользователя,​ начинается со служебного слова ''​DEF''​. В идентификаторе определяемой функции два первых символа (буквы FN) являются обязательными,​ а остальные (α) выбираются автором программы по его желанию. //​Аргументы//​ перечисляются через запятую,​ и вся совокупность //​аргументов//​ заключается в круглые скобки. Отметим,​ что функция пользователя может вообще не иметь аргументов. +
- +
-Каждый //​аргумент//​ является //​формальным//​ параметром:​ это означает,​ что он на самом деле "не существует"​ (память для него не выделяется!) и поэтому не совпадает с переменными,​ имеющими такое же имя в программе. +
- +
-Далее, после символа присваивания "​="​ в записи оператора,​ определяющего функцию пользователя,​ следует выражение β, задающее алгоритм вычисления значения функции пользователя. Это есть "​образец",​ по которому программа каждый раз вычисляет значение функции,​ если, конечно,​ это необходимо. В выражении допустим вызов любой встроенной функции и вызовы других функций пользователя. +
- +
-Приведём примеры //​описания//​ функций пользователя:​ +
-  * 1) <​code>​ +
-        Формальные ​ параметры +
-           │ │      │     │ +
-           ▼ ▼      ▼     ▼ +
-10 DEF FNC(X,​Y)=SQR(X+SIN(Y)) +
-</​code>​ +
-  * 2)  <​code>​ +
-  Параметры (аргументы),​ не являющиеся формальными +
-                │   │ +
-                ▼   ▼ +
-30 DEF FNBUS(Z)=A*Z+B*LOG(ABS(Z))+5467.453*FNC(4,​0.7) +
-             ​▲ ​   ▲           ​▲ ​            ▲ +
-             ​│ ​   │           ​│ ​            │ +
-      Формальный параметр ​  ​Функция пользователя +
-</​code>​ +
-  * 3) <​code>​ +
-   ​Параметр (аргумент),​ не являющийся формальным +
-                              │ +
-                              ▼ +
-100 DEF FNQU$(QU,​ST)=MID$(OL$(QU),​ST) +
-              ▲   ​▲ ​           ▲   ▲ +
-              │   ​│ ​           │   │ +
-               ​Формальные ​ параметры +
-</​code>​ +
-Отметим,​ что //​рекурсия запрещена//​ (и прямая,​ и косвенная!). Кстати,​ о понятии //​рекурсии//​ см. в  [[#IV.4.1. Примеры|разделе IV.4]]. +
- +
-Посмотрите… +
-<​code>​ +
-NEW +
-Ok +
-10 DEF FNY(X)=(X<​1)*FNY(X) +
-20 PRINT FNY(3) +
-run +
-Out of memory in 20 +
-Ok +
-</​code>​ +
-Напомним,​ что //​исполняемым//​ оператором мы называем оператор программы,​ определяющий конкретные действия,​ которые должны быть выполнены. +
- +
-Оператор ''​DEF FN''​ может стоять в любом месте программной строки. Однако,​ он, в отличие от оператора ''​DATA'',​ — //​исполняемый//​ оператор,​ т.е. функция пользователя должна быть определена до обращения к ней. Если же обращение к функции пользователя произведено раньше её определения оператором ''​DEF FN'',​ то на экране дисплея появляется сообщение об ошибке:​ <WRAP centeralign>"​Undefined user function in …" \\ ("​Функция пользователя не определена в строке …"​).</​WRAP>​ +
- +
-Поэтому,​ как правило,​ в начале программы для операторов ''​DEFFN''​ специально резервируется несколько программных строк. +
- +
-Если в ходе выполнения программы,​ необходимо использовать значение функции пользователя,​ определённой в этой программе,​ при заданных значениях её аргументов,​ то необходимо //​вызвать//​ её, т.е. записать идентификатор функции в соответствующее выражение,​ заменив формальные параметры нужными значениями аргументов — //​фактическими//​ параметрами (константами или выражениями). +
- +
-Приведём примеры //​вызова//​ функции пользователя:​ +
-  * a) <​code>​ +
-50 R=FNC(3.07,​5.) +
-          ▲   ▲ +
-          │   │ +
-       ​фактические параметры 3.07 и 5. +
-</​code>​ +
-  * b) <​code>​ +
-90 A=10:​B=2:​D=3.3:​C=FNBUS(5*D-7) +
-                            ▲ +
-                            │ +
-                      фактический параметр 5*D-7 +
-</​code>​ +
-Если выражение β содержит программные объекты (имена переменных,​ элементов массивов,​ функции),​ описанные в качестве формальных параметров в операторе ''​DEF FN'',​ то их значения определяются из списка фактических параметров,​ указываемых при вызове функции пользователя. +
- +
-Если выражение β содержит программные объекты,​ не входящие в список формальных параметров,​ то берутся их "​текущие"​ значения из программы (на момент вызова функции пользователя). +
- +
-В каждом из таких случаев интерпретатор обратится к описанию (определению) соответствующей функции пользователя,​ "​подставит"​ вместо //​формальных//​ параметров необходимые значения //​фактических//​ параметров и произведёт требуемые вычисления,​ после чего результат вычисления значения функции возвращается в точку вызова функции. +
- +
-Другими словами,​ компьютер выполнит над значениями фактических аргументов (параметров) все те действия,​ которые оператор ''​DEF FNα''​ выполняет над своими формальными аргументами. +
- +
-__//​Примеры//​__:​ +
-  * {{anchor:​e043-01}} <​WRAP>​ 1) +
-\\ {{.examples:​043-01.bas|}} \\ [[+tab|wmsxbpge>​043-01.bas]] +
-<​code>​ +
-Ok +
-10 DEF FNP(X)=X^2+X+1:​S=0 +
-           ​▲ ​ ▲   ▲ +
-           ​│ ​ │   │ +
-      Формальный ​ параметр X +
-20 FOR K=1 TO 7 +
-30 S=S+FNP(K) +
-           ▲ +
-           │ +
-   ​Фактический параметр K +
-40 NEXT K +
-50 PRINT S:END +
-run +
-175 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e043-02}} <​WRAP>​ 2) +
-\\ {{.examples:​043-02.bas|}} \\ [[+tab|wmsxbpge>​043-02.bas]] +
-<​code>​ +
-      Формальный параметр X +
-NEW        │  │ +
-Ok         ​▼ ​ ▼ +
-10 DEF FNA(X)=X*7 +
-20 INPUT"​Сколько лет Вашей собаке";​D +
-30 PRINT"​Если бы собака была человеком,​ей было бы";​FNA(D);"​лет!"​ +
-                                                       ▲ +
-                                                       │ +
-                                        Фактический параметр D +
-run +
-Сколько лет Вашей собаке?​ 4 +
-Если бы собака была человеком,​ей было бы 28 лет! +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e043-03}} <​WRAP>​ 3) +
-\\ {{.examples:​043-03.bas|}} \\ [[+tab|wmsxbpge>​043-03.bas]] +
-<​code>​ +
-Аргумент,​ не являющийся формальным параметром +
-NEW                     │ +
-Ok                      ▼ +
-10 DEF FNZ(A,​B)=A^2+B^2+C +
-           ▲ ▲  ▲   ▲ +
-           │ │  │   │ +
-        Формальные параметры A и B +
-20 INPUT X,Y,C +
-30 PRINT FNZ(X,​Y):​END +
-             ▲ ▲ +
-             │ │ +
-        Фактические параметры X и Y +
-run +
-? 2,-3,5 +
- 18 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e043-04}} <​WRAP>​ 4) +
-\\ {{.examples:​043-04.bas|}} \\ [[+tab|wmsxbpge>​043-04.bas]] +
-<​code>​ +
-NEW                                +
-Ok +
-10 DEF FNS$(X$,​K)=MID$(X$,​K,​1) +
-15 DEF FNQ$(X$)=FNS$(X$,​K)+"​$"​ +
-20 INPUT X$,K:PRINT FNQ$(X$):​END +
-run +
-? APR,2 +
-P$ +
-Ok +
- +
-run +
-? betta,4 +
-t$ +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e043-05}} <​WRAP>​ 5) +
-\\ {{.examples:​043-05.bas|}} \\ [[+tab|wmsxbpge>​043-05.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT X:IF X>1 THEN DEF FNY(X)=X^2 ELSE DEF FNY(X)=X^3 +
-20 ? FNY(X):​END +
-run +
-? 2 +
-+
-Ok +
- +
-run +
-? -12 +
--1728 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  * {{anchor:​e043-06}} <​WRAP>​ 6) +
-\\ {{.examples:​043-06.bas|}} \\ [[+tab|wmsxbpge>​043-06.bas]] +
-<​code>​ +
-10 '​Функция FNODD$(N) помогает проверить,​является ли целое число N нечетным:​если значением функции является -1, то число N — нечетное,​ если же значением функции является 0, то число N — четное. +
-20 DEF FNODD(N)=RIGHT$(BIN$(N),​1)="​1"​ +
-</​code>​ +
-</​WRAP>​ +
-Отметим,​ что можно определить 4 различные функции пользователя,​ имеющие одинаковое имя, но различающиеся по типам. +
-  * {{anchor:​e043-07}} <​WRAP>​ 7) +
-\\ {{.examples:​043-07.bas|}} \\ [[+tab|wmsxbpge>​043-07.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 DEF FNQ%=1:DEF FNQ!=2:DEF FNQ=3:DEF FNQ$="​4"​ +
-20 DEFINTQ:​PRINT FNQ; +
-30 DEFSNGQ:​PRINT FNQ; +
-40 DEFDBLQ:​PRINT FNQ:PRINT +
-50 PRINT FNQ%;​FNQ!;​FNQ;​FNQ$ +
-run +
-·1··2··3 +
-·1··2··3·4 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-Этот факт приводит к удивительным последствиям:​ например,​ программа может модифицировать сама себя с помощью динамического изменения вызова функции:​ +
-<​diagram>​ +
-|text1|text1=несоответствие типов формальных и \\ фактических параметров \\ при обращении к функции пользователя +
-||!@4| +
-|ошибка| ──▶ +
-||!@4| +
-|обработка прерывания по ошибке ("​ловушка"​ ошибки)| ──▶ +
-||!@4| +
-|изменение типа функции пользователя| +
-</​diagram>​ +
- +
-  * {{anchor:​e043-08}} <​WRAP>​ 8) +
-\\ {{.examples:​043-08.bas|}} \\ [[+tab|wmsxbpge>​043-08.bas]] +
-<​code>​ +
-NEW +
-Ok +
-5 ON ERROR GOTO 100 +
-10 DEF FNY(X)=X^3 +
-15 DEF FNY$(X$)=X$+"​(Козьма Прутков)"​ +
-18 DEFSTR X +
-20 LINEINPUT X:PRINT FNY(X):​END +
-100 IFERR=13 THEN DEFSTR Y:​RESUME0'​Код 13 имеет ошибка"​Type mismatch"​! +
-run +
-Смотри в корень! +
-Смотри в корень!(Козьма Прутков) +
-Ok +
-</​code>​ +
-(см. раздел [[08#​VIII.3.4. Программная обработка ошибок|VIII.3.4.]]). +
-</​WRAP>​ +
-Поскольку выражение β, содержащее алгоритм вычисления значения функции пользователя,​ хранится в памяти компьютера как //​часть программы//,​ то ''​DEFFN''​ — один из нескольких операторов,​ которые нельзя использовать в режиме прямого выполнения команд (это пример //​оператора//,​ который не является //​командой//​ !). +
-  * 9) <​code>​ +
-Ok +
-DEF FNR(X)=X^5:​PRINT FNR(2) +
-Illegal direct +
-Ok +
-</​code>​ +
-Сообщение об ошибке "​Illegal direct"​ означает,​ что в качестве команды непосредственного выполнения встречается оператор,​ недопустимый в этом режиме. +
- +
-Учтите,​ что если Вы допустили ошибку во время определения функции,​ эта ошибка будет обнаружена только тогда, когда функция встретится в выражении. Компьютер будет указывать как на источник ошибки на ту строку текста,​ где использована неверно заданная функция,​ а не на ту строку,​ где эта функция была определена! +
- +
-===== IV.4. Подпрограммы ===== +
- +
-Прежде всего отметим,​ что //​подпрограммы//​ — это специальным образом оформленные группы программных строк. Подпрограммы бывают двух типов: //​стандартные//​ и //​нестандартные//​. +
- +
-Первые из них входят в состав математического обеспечения компьютера. Нам часто приходится неявным образом обращаться к ним, когда, например,​ вводим данные в память,​ печатаем результаты счета, вычисляем значения встроенных функций и т.п. +
- +
-//​Нестандартные//​ подпрограммы составляются самим пользователем и являются фактически фрагментами его программ. +
- +
-В виде подпрограмм целесообразно оформлять логически завершённые части алгоритма,​ имеющие самостоятельную ценность;​ кроме того, использование подпрограмм позволяет экономить время и место в том случае,​ когда нужно в одной и той же программе несколько раз выполнить какую–либо последовательность операторов.Вместо того, чтобы многократно переписывать эту последовательность,​ напишите единственный программный //​модуль//,​ к которому Вы сможете обращаться всякий раз при необходимости. +
- +
-Подпрограмма,​ следовательно,​ играет в какой–то степени ту же роль, что в математике "​теорема"​ или "​лемма":​ когда нужно доказать результат в некоторой специальной области,​ например,​ в дифференциальной геометрии,​ вовсе не обращаются каждый раз к базовым аксиомам теории множеств,​ а опираются на теоремы,​ которые косвенно через несколько уровней абстракции основываются на этих аксиомах. +
- +
-{{anchor:​gosub}} +
-Общая форма записи оператора обращения к подпрограмме (оператора вызова подпрограммы) следующая:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-GOSUB n +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где:  +
-  * ''​GOSUB''​ ("GO to SUBroutine"​ — "​идти к подпрограмме"​) — служебное слово;​ +
-  * n — номер первой строки подпрограммы,​ 0≤n≤65529. +
-Разумеется,​ нежелательно,​ чтобы строка с номером n находилась внутри цикла! +
- +
-Использование несуществующего номера программной строки n вызывает по явление на экране дисплея сообщения об ошибке вида: <WRAP centeralign>"​Undefined line number"​ \\ (//"​Не определён номер строки"//​).</​WRAP>​ +
- +
-{{anchor:​return}} +
-Подпрограмма,​ как правило (!), завершается оператором +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-RETURN +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где ''​RETURN''​ ("​return"​ — "​возврат"​) — служебное слово. +
- +
-Оператор ''​GOSUB n''​ используется для вызова подпрограммы — группы операторов,​ начинающихся программной строкой с номером n и заканчивающихся оператором ''​RETURN''​. Подпрограмма может начинаться с комментария и находиться в любом месте Вашей программы. +
- +
-Главной особенностью оператора ''​GOSUB''​ является то, что оператор ''​RETURN''​ возвращает управление оператору,​ стоящему за последним выполненным оператором ''​GOSUB''​. Заметим,​ что оператор,​ которому возвращается управление,​ может находиться не на следующей,​ а на той же программной строке! +
-Приведём пример:​ +
-{{anchor:​e044-01}} {{.examples:​044-01.bas|}} \\ [[+tab|wmsxbpge>​044-01.bas]] +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-Ok +
-100 X=2 +
-110 GOSUB 200:X=3 +
-120 GOSUB 200 +
-125 X=4 +
-140 END +
-200 PRINT X^X +
-210 RETURN +
-run +
- 4 +
- 27 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
- +
-<WRAP half column>​ +
-<​code>​ +
-    Ok           ​┌──────────────────┐ +
-    100 X=2      ▼                  │ +
-┌── 110 GOSUB 200:​X=3 ​              │ +
-│ ┌ 120 GOSUB 200                   │ +
-│ │ 125 X=4      ◀─ ─ ─ ─ ─ ─ ─ ─ ┐ │ +
-│ │ 140 END                       │ │ +
-│ │                               │ │ +
-│ └─ ─ ─ ─ ─ ─ ─ ┐                │ │ +
-│                ▼                │ │ +
-└─────────────▶ ┌───────────────┐ │ │ +
-                │ 200 PRINT X^X │ │ │ +
-                │ 210 RETURN ​   │─┘─┘ +
-                └───────────────┘ +
-</​code>​ +
-</​WRAP>​ +
-</​WRAP>​ +
-Оператор ''​GOSUB n''​ может показаться очень похожим на оператор ''​GOTO n''​. Существенная разница между ними в том, что оператор ''​GOSUB''​ как бы "​посылает в командировку"​ — после ​ выполнения операторов подпрограммы происходит возвращение назад. +
-<​code>​ +
-  Основная программа ​ │           ​Подпрограмма +
-┌───────────────────┐ ▼─────────▶┌────────────┐ +
-│       ​GOSUB ​      │ │         ​││ ​           │ +
-│         ​… ​        │ │         ​││ ​           │ +
-│       ​GOSUB ​      │ ▼         ​││ ​           │ +
-│         ​… ​        │ │         ​││ ​           │ +
-│        END        │ │         ​││ ​  ​RETURN ​  │ +
-└───────────────────┘ ▼         ​▼└────────────┘ +
-</​code>​ +
-//Все// переменные в подпрограмме являются //​глобальными//​. Это означает,​ что "​доступ"​ к их значениям возможен из //​любого//​ места Вашей основной программы. +
- +
-Глобальная переменная — переменная,​ областью существования которой является вся программа. Локальная переменная — переменная с ограниченной областью существования в программе. +
- +
-Образно говоря,​ переменные,​ имеющие одно и то же имя в основной (вызывающей) программе и подпрограмме не "​однофамильцы",​ а одно и то же лицо! +
- +
-При вызове подпрограммы значения переменных в основной программе не "​замораживается",​ а могут быть изменены операторами подпрограммы! Без "​замораживания"​ то и дело происходят пренеприятнейшие вещи. +
- +
-Представьте себе, что Вы подарили своему товарищу очень ценную для него подпрограмму и объяснили,​ как ею пользоваться. Разумеется,​ Вашему товарищу нет никакого дела до того, какие имена переменных Вы использовали в Вашей подпрограмме. Поэтому может случиться,​ что и в его основной программе будут использоваться переменные с теми же именами,​ что и в подаренной Вами подпрограмме. Ясно, что эти переменные "​неразличимы"​ для интерпретатора. Дальнейшее ужасно! +
- +
-Как говорят программисты,​ в [[msx:​basic:​]] постоянно присутствует "​побочный эффект подпрограммы"​! +
- +
-Следовательно,​ важно выделить конкретные имена переменных,​ используемых //​только//​ в данной подпрограмме и применить их для передачи значений аргументов из основной программы и возвращения результатов работы подпрограммы в основную программу. +
- +
-Впрочем,​ оператор ''​RESTORE''​ (см. [[02#​II.4.5. Операторы ввода данных DATA и READ. Оператор RESTORE|раздел II.4.5.]]) предоставляет возможность каждой подпрограмме иметь свои собственные (//​локальные//​) переменные. Необходимо просто при //​каждом//​ обращении к ней выполнять оператор ''​RESTORE''​ для установки указателя на начало данных подпрограммы. +
- +
-{{anchor:​e044-02}} __//​Пример//​__. \\ {{.examples:​044-02.bas|}} \\ [[+tab|wmsxbpge>​044-02.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 DATA 5,​2:'​Данные основной программы +
-20 DATA 7,​.5:'​Данные подпрограммы +
-30 READ A,​B:?​A+B;:​GOSUB 40:?​A+B:​END +
-40 RESTORE 20:READ A,​B:?​A+B;:​RESTORE 10:​READA,​B:​RETURN'​A и B - локальные переменные подпрограммы! +
-run +
-·7··7.5··7 +
-Ok +
-</​code>​ +
-Наиболее распространённой ошибкой при использовании подпрограмм является их неполное отделение от основной программы. Основными способами защиты от указанной ошибки являются:​ +
-  - <​WRAP>​ использование оператора ''​END'';​ например,​ если //​пакет//​ подпрограмм (совокупность нескольких подпрограмм) начинается с программной строки 100, то строка основной программы +
-  99 END +
-предотвратит вход в подпрограмму,​ начинающуюся со строки 100; +
-</​WRAP>​ +
-  - <​WRAP>​ использование в основной программе перед первой строкой подпрограммы оператора ''​GOTO k'',​ где k — номер программной строки,​ расположенной за строкой,​ в которой расположен оператор ''​RETURN''​ данной подпрограммы (см. пример из [[#IV.4.1. Примеры|раздела IV.4.1.]]). +
-</​WRAP>​ +
- +
-Поэтому сформулируем важный практический вывод. +
- +
-**Помещайте подпрограммы или в //​самом конце//​ или в //​самом начале//​ основной программы !** +
- +
-При случайном(!) попадании в подпрограмму без использования оператора ''​GOSUB''​ она выполнится нормально,​ но компьютер выдаст сообщение об ошибке <WRAP centeralign>"​RETURN without ​ GOSUB" \\ ("​RETURN //без// GOSUB"​).</​WRAP>​ +
- +
-Однако,​ если Вы случайно забыли поставить оператор ''​RETURN'',​ то интерпретатор может иногда не заметить ошибку! Он будет тщетно искать "​забытый"​ оператор ''​RETURN''​ до конца программы,​ и, не найдя, прекратит все вычисления (т.к. программа уже будет выполнена полностью). Сообщения об ошибке не будет! Берегитесь! +
- +
-Учтите,​ что операторы,​ стоящие за оператором ''​RETURN''​ в той же программной строке,​ //​никогда//​ не выполняются,​ поэтому за оператором ''​RETURN''​ целесообразно помещать только комментарии. +
- +
-Например,​  +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-50 RETURN '​──▶ +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
- +
-</​WRAP>​ +
-</​WRAP>​ +
-или  +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-50 RETURN ──▶ +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-Поговорим теперь о совместном использовании операторов ''​FOR…NEXT''​ и ''​GOSUB n''​. +
- +
-Внутри цикла использовать оператор ''​GOSUB'',​ //​можно//,​ но оператор ''​NEXT''​ должен быть выполнен только //​после//​ выполнения оператора ''​RETURN''​. +
- +
-В противном случае последует сообщение:​ <WRAP centeralign>"​NEXT without FOR" \\ ("NEXT //без// FOR"​).</​WRAP>​ +
- +
-{{anchor:​e044-03}} __//​Пример//​__. \\ {{.examples:​044-03.bas|}} \\ [[+tab|wmsxbpge>​044-03.bas]] +
-<​code>​ +
-NEW +
-Ok +
-5 INPUT K,N:FOR I=1 TO N:GOSUB 100:PRINT I;:​NEXTI:​END +
-100 IF K>I THEN NEXTI:​RETURN ELSE RETURN +
-run +
-? 2,6 +
-NEXT without FOR in 100 +
-Ok +
- +
-run +
-? 0,6 +
-·1··2··3··4··5··6 +
-Ok +
-</​code>​ +
-С другой стороны,​ если цикл ''​FOR…NEXT''​ используется в подпрограмме,​ то оператор ''​RETURN'',​ находящийся в цикле ''​FOR…NEXT'',​ позволяет выйти из цикла и вернуться в основную программу. Это наводит на мысль, что наиболее эффективно размещать процедуру поиска элемента массива,​ обладающего требуемыми свойствами,​ //​внутри//​ подпрограммы. Как только искомый элемент будет найден,​ выполнится выход из подпрограммы. +
- +
-Однако учтите,​ что в момент выполнения оператора ''​RETURN''​ любой незаконченный цикл ''​FOR…NEXT''​ в подпрограмме заканчивается и часть стекового пространства,​ которое он (цикл) занимал,​ освобождается! +
- +
-{{anchor:​e044-04}} __//​Пример//​__. \\ {{.examples:​044-04.bas|}} \\ [[+tab|wmsxbpge>​044-04.bas]] +
-Вывести на экран дисплея первое нечётное число, встретившееся в целочисленном массиве A(K). +
-<​code>​ +
-NEW +
-Ok +
-10 DEFINT A:INPUT K:DIM A(K):DATA 2,1,4,7,8 +
-30 FOR I=1 TO K:READ A(I):​NEXTI:​GOSUB 100:END +
-100 FOR J=1 TO K:IF VAL(RIGHT$(STR$(A(J)),​1))MOD2=1THEN?​A(J):​RETURN ELSE NEXTJ +
-120 PRINT "​нечетных элементов в массиве нет":​RETURN +
-run +
-? 3 +
- 1 +
-Ok +
- +
-run +
-? 5 +
-+
-Ok +
-</​code>​ +
-При многократном выполнении выхода из подпрограмм с помощью операторов ''​GOTO'',​ ''​ON GOTO''​ или ''​IF…THEN…ELSE''​ (вместо оператора ''​RETURN''​) в конце концов на экране может появиться сообщение об ошибке:​ <WRAP centeralign>"​Out of memory"​ \\ (//"​Не хватает памяти"//​).</​WRAP>​ +
- +
-Причина возникающей ошибки довольно своеобразна:​ дело в том, что интерпретатор отводит сравнительно небольшой участок динамической памяти для хранения списка адресов возврата из подпрограмм. Такой список организуется в виде стека и называется //​рабочим стеком//​. Каждый раз при вызове подпрограммы в стек заносится соответствующий этому вызову //​адрес возврата//,​ занимающий 7 байт. При выполнении оператора ''​RETURN''​ из стека извлекается адрес возврата,​ записанный последним,​ и происходит передача управления по этому адресу,​ после чего он удаляется из стека. Операторы,​ подобные ''​GOTO''​ или ''​IF…THEN…ELSE'',​ осуществляют выход из подпрограммы,​ не затрагивая стека! Если такой выход из подпрограмм происходит часто, то адреса из стека не удаляются,​ а лишь добавляются при каждом новом вызове подпрограммы,​ так что в результате размер стека может превысить величину отведённого ему участка памяти. В итоге программа прекращает работу,​ и выдаётся сообщение об ошибке. +
- +
-{{anchor:​e044-05}} __//​Пример//​__. \\ {{.examples:​044-05.bas|}} \\ [[+tab|wmsxbpge>​044-05.bas]] +
-<​code>​ +
-10 GOSUB 20:END +
-20 FOR I=1 TO 1:​K=K+1:​GOTO 10:​NEXTI:​RETURN +
-run +
-Out of memory in 20 +
-Ok +
- +
-а теперь… print K +
-·894 +
-Ok +
-</​code>​ +
- +
-В программе может быть несколько операторов ''​RETURN'',​ относящихся к одному оператору ''​GOSUB n''​. Отметим,​ что наличие оператора ''​RETURN''​ в некотором месте подпрограммы ещё не означает фактического окончания подпрограммы в данном месте. +
- +
-{{anchor:​e044-06}} __//​Пример//​__. Написать программу,​ вычисляющую значение функции y=│x+x²│ в точке x=A (не применяя функции ''​ABS()''​). ​ \\ {{.examples:​044-06.bas|}} \\ [[+tab|wmsxbpge>​044-06.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT A:​U=A+A^2:​GOSUB 100:PRINT Z:END +
-100 '​Подпрограмма вычисления │x│: аргумент U, результат Z +
-110 IF U>=0 THEN Z=U:RETURN ELSE Z=-U:​RETURN +
-run +
-? -4 +
- 12 +
-Ok +
-</​code>​ +
-Подпрограмма может, в свою очередь,​ вызывать другую подпрограмму,​ та — другую и так далее. Глубина вложения (степень вложения) подпрограмм ограничивается лишь размерами стека. +
- +
-Наглядно это можно представить себе следующим образом. Пусть Вас из Куйбышева послали в Москву на повышение квалификации,​ а оттуда ещё в Ленинград на курсы. По окончании этих курсов Вы возвращаетесь в Москву,​ заканчиваете учёбу там и только после этого возвращаетесь домой. +
- +
-Вложенные подпрограммы являются довольно мощным средством разработки и отладки больших программ. Используя принцип вложений,​ можно не только разбивать сложную программу на отдельные модули и для каждого из них писать свою подпрограмму,​ но и //​разделять//​ на //​модули//​ любые подпрограммы. Чем меньше будет каждый выделенный программный модуль,​ тем легче будет его программировать и отлаживать и тем больше вероятность его многократного использования в других программах! +
- +
-"​Трудности,​ обусловленные бессистемным написанием (без использования модульной структуры) большой и сложной программы,​ можно сравнить с трудностями,​ возникающими при попытке съесть сразу //​целиком//​ весь батон колбасы;​ в то же время, если разрезать колбасу на ломтики,​ то съесть её не представит никакого труда"​ (Л.Пул). +
- +
-{{anchor:​e044-07}} Приведём пример,​ иллюстрирующий вложение подпрограмм:​ +
-\\ {{.examples:​044-07.bas|}} \\ [[+tab|wmsxbpge>​044-07.bas]] +
-<​code>​ +
-NEW +
-Ok +
-1' Программа вычисления суммы вида +
-2' ​            ​k ​   k        k +
-3' ​       S = x  + x  +...+ x  , +
-4' ​            ​1 ​   2        n +
-5' где x - корни линейного алгебраического уравнения n-ой степени +
-6' ​     i         +
-7'​Алгоритм решения поставленной задачи основан на формулах Ньютона,​ приведенных в книге: А.П.Мишина,​ И.В.Проскуряков "​Высшая алгебра"​. М.:​ГИФМЛ,​ 1962, гл.III, 3, с.245. +
-11 INPUT "​Укажите степень многочлена";​N:​INPUT"​Укажите k";K +
-15 DIM A(N) '​Описан массив коэффициентов уравнения! +
-18 PRINT"​Вводите коэффициенты уравнения"​ +
-20 FOR I=0 TO N:INPUT A(I):NEXT '​Итак,​ массив А(N) введен! +
-40 DIM SIG(N):FOR I=1 TO N:​SIG(I)=(-1)^I*A(I)/​A(0):​NEXTI +
-80 IF N>=K THEN DIM S(N):​A1=N:​A2=K:​GOSUB 200 ELSE DIM S(K):​A1=K:​A2=N:​GOSUB 300 +
-110 PRINT S(K):END +
-200 '​¤¤¤¤¤ Начало подпрограммы 1 ¤¤¤¤¤ +
-205 S(1)=SIG(1):​FOR J=2 TO A2:​S(J)=(-1)^(J+1)*J*SIG(J) +
-230 FOR I=1 TO J-1:​S(J)=S(J)+(-1)^(J-I+1)*S(I)*SIG(J-I) +
-250 NEXTI:​NEXTJ:​RETURN '​──▶ +
-300 '​¤¤¤¤¤ Начало подпрограммы 2 ¤¤¤¤¤ +
-305 GOSUB 200  '​Вот оно, ​ в л о ж е н и е  подпрограмм! +
-360 FOR J=N+1 TO K:S(J)=0 +
-380 FOR I=1 TO N:​S(J)=S(J)-(-1)^S(J-I)*SIG(I) +
-400 NEXT I,J:RETURN '​──▶ +
-run +
-Укажите степень многочлена?​ 2 +
-Укажите k? 2 +
-Введите коэффициенты уравнения +
-? 1 +
-? 0 +
-? -1  +
- 2 +
-Ok +
-</​code>​ +
- +
-==== IV.4.1. Примеры ==== +
- +
-{{anchor:​e0441-01}} __//​Пример 1//__. Написать программу,​ вычисления числа сочетаний из <​m>​m</​m>​ по <​m>​n</​m>​ по формуле:​ \\ <m>C matrix{2}{1}{n {m}}={m!}/​{n!(m-n)!},​ (m>​=n)</​m>​. +
- +
-Целесообразно разработать подпрограмму вычисления факториала и затем трижды (почему?​) обратиться к ней из основной программы. Итак, +
-\\ {{.examples:​0441-01.bas|}} \\ [[+tab|wmsxbpge>​0441-01.bas]] +
-<​code>​ +
-NEW +
-Ok +
-40 INPUT "​Введите значения m,​n";​M,​N:​GOTO 100' ───┐ +
-50 '​Подпрограмма вычисления факториала F!        │ +
-60 F=1:FOR J=1 TO K:​F=F*J:​NEXTJ' ​                │ +
-90 RETURN '​Конец подпрограммы! ​                  │ +
-100 K=M:GOSUB 60:​M1=F' ​   ◀──────────────────────┘ +
-110 K=N:GOSUB 60:N1=F +
-120 K=M-N:GOSUB 60:R1=F +
-130 CMN=M1/​N1/​R1 +
-140 ? "​Число сочетаний из М=";​M;"​по N=";​N;"​равно";​CMN:​END +
-run +
-Введите значения m,n? 6,3 +
-Число сочетаний из M= 6 по N= 3 равно 20 +
-Ok +
-</​code>​ +
-Заметим,​ что оператор ''​GOSUB''​ может оказаться полезным в качестве команды прямого режима. Если Ваша программа состоит из подпрограмм,​ которые Вы хотите проверить,​ то, используя команду ''​GOSUB''​ в прямом режиме,​ можно войти в любую подпрограмму. После выполнения оператора ''​RETURN''​ система [[msx:​basic:​]] +
-снова вернётся в режим прямого выполнения команд. +
- +
-В примере 1, например,​ можно проверить работоспособность подпрограммы следующим образом (находясь в прямом режиме!):​ +
-<​code>​ +
-F=1:​k=4:​GOSUB 60 +
-Ok +
-print F +
- 24 +
-Ok +
-</​code>​ +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Ибо это недостойно совершенства человеческого,​ +
-подобно рабам тратить часы на вычисления. +
-<WRAP rightalign>​ +
-—//​Г.В.Лейбниц//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-{{anchor:​e0441-02}} __//​Пример 2//__. Составить программу,​ которая позволяет методом половинного деления (дихотомии) на отрезке [A,B] с точностью E определить какой–либо (!) вещественный корень уравнения ​ F(x)=0, где F(x) непрерывна на [A,B] и на концах отрезка принимает значения разных знаков (F(A)·F(B)<​0). +
-Пусть, например,​ +
-<​m>​F(x)=cos e^x-sin pi^x, A=1, B=3, E=0.00001.</​m>​ +
-\\ {{.examples:​0441-02.bas|}} \\ [[+tab|wmsxbpge>​0441-02.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT A,B,E +
-20 X=A:GOSUB 200:F1=Y +
-30 X=(A+B)/2 +
-40 GOSUB 200:F2=Y:IF Y=0 THEN 90 +
-50 IFSGN(F1)*SGN(F2)>​0 THEN 70 +
-60 B=X:GOTO 80 +
-70 A=X:F1=F2 +
-80 IF B-A>E THEN 30 +
-90 PRINTUSING "​Корень####​.#####​ точность##​^^^^";​X,​E +
-100 END +
-200 Y=COS(EXP(X))-SIN(EXP(X*LOG(3.14159))) +
-210 RETURN +
-run +
-? 1,​3,​.00001 +
-Корень···1.27163·точность·1Е-05 +
-Оk +
-</​code>​ +
- +
-{{anchor:​e0441-03}} __//​Пример 3//__. Если у Вас есть знакомый художник,​ попросите его разделить произвольный отрезок на две неравные части. Возможно он сделает это в золотом отношении,​ если его чувство меры воспитано на классических образцах. +
- +
-Такое чувство меры целесообразно "​внушить"​ компьютеру,​ которому часто приходится отыскивать единственную точку минимума некоторой функции y=f(x) на отрезке [a,b]. Основа алгоритма — последовательное приближение к минимуму до достижения заданной точности E. +
-\\ {{.examples:​0441-03.bas|}} \\ [[+tab|wmsxbpge>​0441-03.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 '​Поиск минимума функции y=f(x) на отрезке [a,b] методом золотого сечения +
-20 DEFFN Y(X)=-X^2+5:​ '​Вид функции +
-30 INPUT"​A,​B,​точность";​A,​B,​E +
-40 GOSUB 110:​GOSUB120 +
-50 IF ABS(B-A)<​E THEN 90 +
-60 IF Y1>Y2 THEN 70 +
-65 B=X2:​X2=X1:​Y2=Y1:​GOSUB 110:GOTO 80 +
-70 A=X1:​X1=X2:​Y1=Y2:​GOSUB120 '​──▶ +
-80 GOTO 50 +
-90 X=(A+B)/​2:​PRINT"​Y мин=";​FNY(X);"​при x=";​X +
-100 END +
-110 X1=.618*A+.382*B:​Y1=FNY(X1):​RETURN '​──▶ +
-120 X2=.382*A+.618*B:​Y2=FNY(X2):​RETURN '​──▶ +
-run +
-A,​B,​точность?​ -1,4 +
-?? 0.00001 +
-Y мин=-10.999971821564 при x= 3.999996477694 +
-Ok +
-</​code>​ +
-{{anchor:​e0441-04}} __//​Пример 4.//__ +
-Вычислить \\ <​m>​{1/​pi}*int{0}{pi}{delim{[}{ {sin(10*x)}/​{sin(x)} }{]}^{6}}dx</​m>​ по формуле парабол (формуле Симпсона). Внимание! Интеграл несобственный! +
-\\ {{.examples:​0441-04.bas|}} \\ [[+tab|wmsxbpge>​0441-04.bas]] +
-<​code>​ +
-NEW +
-Ok +
-20 INPUT "​Нижний предел";​A +
-30 INPUT "​Верхний предел";​B +
-40 INPUT "​Количество точек";​M +
-70 S=0:​H=(B-A)/​M +
-80 S1=0:FOR X=A+H/2 TO B-H/2 STEP H +
-90 GOSUB 180:​S1=S1+Y:​NEXT:​S1=S1*4 +
-100 S2=0:FOR X=A+H TO B-H STEP H +
-110 GOSUB 180:​S2=S2+Y:​NEXT:​S2=S2*2 +
-120 X=A:GOSUB 180:S=S+Y +
-130 X=B:GOSUB 180:S=S+Y +
-140 S=(S+S1+S2)*H/​6 +
-160 PRINT"​Интеграл = ";​S:​END +
-180 Y=(SIN(10*X)/​SIN(X))^6/​(4*ATN(1)):​RETURN ──▶ +
-run +
-Нижний предел?​ 0.00000001 +
-Верхний предел?​ 3.14159265 +
-Количество точек? 250 +
-Интеграл =  55251.99567425 +
-Ok                                  +
- +
-run +
-Нижний предел?​ 0.00000001 +
-Верхний предел?​ 3.14159265 +
-Количество точек? 500 +
-Интеграл =  55251.995674258 +
-Ok +
-</​code>​ +
-{{anchor:​e0441-05}} __//​Пример 5//__. Написать программу,​ осуществляющую лексикографическое упорядочение (расположение в алфавитном порядке) массива фамилий на русском языке (после фамилий можно указывать инициалы,​ например:​ Бобров А.В.). +
-\\ {{.examples:​0441-05.bas|}} \\ [[+tab|wmsxbpge>​0441-05.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 DATA " ","​.","​А","​Б","​В","​Г","​Д","​Е","​Ж","​З","​И","​Й","​К","​Л","​М","​Н","​О","​П","​Р","​С","​Т","​У","​Ф","​Х","​Ц","​Ч","​Ш","​Щ","​Ы","​Ь","​Э","​Ю","​Я"​ +
-15 DATA " ","​.","​-","​а","​б","​в","​г","​д","​е","​ж","​з","​и","​й","​к","​л","​м","​н","​о","​п","​р","​с","​т","​у","​ф","​х","​ц","​ч","​ш","​щ","​ы","​ь","​э","​ю","​я"​ +
-20 INPUT"​Введите количество фамилий";​S:​DIM C$(S) +
-30 FOR I=1TOS:​INPUT"​Введите очередную фамилию";​C$(I):​NEXTI +
-40 GOSUB 190 +
-50 DIM N(L1,S) +
-56 FOR I=1 TO S:RESTORE 10:FOR J=1 TO 33:READB$ +
-57 IF B$=MID$(C$(I),​1,​1) THEN N(1,I)=J +
-58 NEXTJ +
-70 FOR K=2 TO LEN(C$(I))-4 +
-71 IF MID$(C$(I),​K-1,​1)="​-"​THEN RESTORE 10 ELSE RESTORE 15 +
-80 FOR J=1 TO 34 +
-90 READ B$:IF B$=MID$(C$(I),​K,​1) THEN N(K,I)=J +
-100 NEXT J,K +
-101 FOR K=LEN(C$(I))-3 TO L1:RESTORE 10 +
-103 FOR J=1 TO 33 +
-105 READ B$:IF B$=MID$(C$(I),​K,​1) THEN N(K,I)=J +
-107 NEXT J,K +
-108 NEXT I +
-110 FOR K=1 TO L1 +
-120 FOR I=1 TO S-1:​FORJ=I+1 TO S +
-130 IF MID$(C$(I),​1,​K)=MID$(C$(J),​1,​K) THEN GOTO 140 ELSE IF(N(K,​I)>​N(K,​J))AND(MID$(C$(I),​1,​K-1)=MID$(C$(J),​1,​K-1)) THEN SWAP C$(I),​C$(J):​FOR L=1 TO L1:SWAP N(L,​I),​N(L,​J):​NEXT L +
-140 NEXT J,I,K +
-150 CLS '​Очистим экран дисплея! +
-160 PRINT SPC(10);"​Итоговый список"​ +
-170 FOR I=1 TO S:PRINT SPC(10);​STR$(I);"​. ";​C$(I):​NEXTI +
-180 END +
-190 L1=0:FOR P=1 TO S:IF LEN(C$(P))>​L1THEN L1=LEN(C$(P)) +
-200 NEXT:​RETURN +
-run +
-Введите количество фамилий?​ 4 +
-Введите очередную фамилию?​ Ухин И.Н. +
-Введите очередную фамилию?​ Ми-Ка М.У. +
-Введите очередную фамилию?​ Ми-Ша А.А. +
-Введите очередную фамилию?​ Лим А. +
-Итоговый список +
-1. Лим А. +
-2. Ми-Ка М.У. +
-3. Ми-Ша А.А. +
-4. Ухин И.Н. +
-Ok +
-</​code>​ +
-{{anchor:​e0441-06}} __//​Пример 6//__. Абсолютно простым числом назовём натуральное число, обладающее следующим свойством:​ при любой перестановке цифр данного числа образуется также простое число. Найдите все абсолютно простые числа, принадлежащие [C,E]. +
-\\ {{.examples:​0441-06.bas|}} \\ [[+tab|wmsxbpge>​0441-06.bas]] +
-<​code>​ +
-NEW +
-Ok +
-1 CLS '​Вначале очистим экран! +
-2 INPUT"​Введите два натуральных числа через запятую,​ причём второе число должно быть больше первого (эти числа задают диапазон,​ в котором ищутся абсолютно простые числа)";​C,​E +
-3 PRINT"​Вы хотите узнать всю правду об абсолютно простых числах,​ лежащих на отрезке [";​C;",";​E;"​] ? Пожалуйста..."​ +
-4 FOR A=C TO E:IF A<​10AND(A=1ORA=2ORA=3ORA=5ORA=7)THEN PRINTA;:​NEXTA ELSE IF A<​10AND(A=4ORA=6ORA=8ORA=9)THEN NEXTA ELSE A$=MID$(STR$(A),​2) +
-5 N=LEN(A$):​DIM A(N) +
-10 FOR L=1TO N:​A(L)=VAL(MID$(A$,​L,​1)):​NEXT L:GOSUB 200 +
-20 I=N +
-30 GOTO 110 +
-40 GOSUB 300:J=N-1 +
-50 IF A(J)>​=A(J+1)ANDJ>​0 THEN J=J-1:GOTO 50 +
-60 I=J +
-70 IF I>0 THEN J=N:GOTO 80 ELSE GOTO 110 +
-80 IF A(I)>​=A(J) THEN J=J-1:GOTO 80 +
-90 SWAP A(I),​A(J):​P1=I+1:​P2=N +
-100 IF P1<P2 THEN SWAP A(P1),​A(P2):​P1=P1+1:​P2=P2-1:​GOTO100 +
-110 IF I>0 THEN GOTO 40 +
-120 ERASEA:IF JJ<>1 THEN PRINT A;:NEXT AELSE JJ=0:​NEXTA +
-125 PRINT:​PRINT"​Надеюсь,​ Вы остались довольны?​!"​ +
-130 END +
-190 '​Подпрограмма,​ производящая сортировку массива A(N), состоящего из цифр числа А. +
-200 FOR M=1 TO N-1:FOR S=M+1 TO N +
-210 IFA(M)<​=A(S)THEN NEXT:NEXT ELSE SWAP A(M),​A(S):​NEXT:​NEXT +
-220 RETURN  +
-290 '​Подпрограмма,​ позволяющая определить,​ является ли число V, составленное из цифр числа A, простым. +
-300 V=0:FOR P=1TON:​V=V+A(P)*10^(N-P):​NEXT +
-310 FOR Q=2 TO INT(SQR(V)) +
-320 IF VMODQ=0 THEN JJ=1:RETURN ELSE NEXT Q:RETURN +
-run +
- +
-Введите два натуральных числа через запятую,​ причём второе число должно быть больше первого (эти числа задают диапазон,​ в котором ищутся абсолютно простые числа)?​ 1,100 +
- +
-Вы хотите узнать всю правду об абсолютно простых числах,​лежащих на отрезке [1, 100] ? Пожалуйста… +
-·1··2··3··5··7··11··13··17··31··37··71··73··79··97 +
-Надеюсь,​ Вы остались довольны?​ +
-Ok +
-</​code>​ +
-{{anchor:​e0441-07}} __//​Пример 7//__. +
-\\ {{.examples:​0441-07.bas|}} \\ [[+tab|wmsxbpge>​0441-07.bas]] +
-<​code>​ +
-10'​**************************************************** +
-30'​* ​              ​Программа ​ LONGMULT ​               * +
-50'​* ​  ​позволяет найти точное значение произведения ​  *  +
-70'​* ​          не более чем 210-значных чисел ​        * +
-81'​* ​            ​Мах. время работы - 1.5 мин. ​        * +
-83'​**************************************************** +
-90 CLEAR 1000:​DIMA(30),​C(31,​61),​D(62),​D$(62),​B(30),​S(62):​CC=10000000! +
-92 DEFFND$(X)=RIGHT$("​0000000"​+RIGHT$(STR$(X),​LEN(STR$(X))-1),​7):​CLS +
-100 PRINT"​Введите 1-й множитель":​PRINT"​a=";:​GOSUB 150 +
-110 FOR I=1TO N:​A(I)=S(1):​NEXT:​NA=N +
-120 ?:​PRINT"​Введите 2-й множитель":​PRINT"​b=";:​GOSUB 150 +
-130 FOR I=1 TO N:​B(I)=S(I):​NEXT:​NB=N:​GOSUB 190 +
-135 IF D(1)=0 THEN S=2 ELSE S=1 +
-140 PRINT:​PRINT"​a*b=";:​FOR I=S TO NA+NB:PRINT FND$(D(I));:​NEXT +
-145 PRINT :​PRINT:​END +
-150 VV$=""​ +
-160 S$=INKEY$:​IF S$=""​THEN160 ELSE IF S$=CHR$(13) THEN PRINT:​GOTO170 ELSE IF ASC (S$)<48 OR ASC(S$)>​57 THEN160 ELSE PRINT S$;:​VV$=VV$+S$:​GOTO160 +
-170 N=LEN(VV$):​IFNMOD7=0THEN180 ELSE VV$="​0"​+VV$:​ GOTO170 +
-180 N=N/7:FOR I=1 TO N:​S(I)=VAL(MID$(VV$,​1+(I-1)*7,​7)):​NEXT:​RETURN +
-190 '​∗∗∗ Собственно длинное умножение ∗∗∗ +
-200 FOR I=NB TO 1 STEP-1:​S=0 +
-210 FOR J=NA TO 0 STEP-1 +
-220 C(I,​J+I)=S+B(I)*A(J)-INT((S+B(I)*A(J))/​CC)*CC:​S=INT((S+B(I)*A(J))/​CC):​NEXT:​NEXT +
-230 S=0:​FORJ=NA+NBTO1 STEP-1:​FORI=1TONB:​D(J)=D(J)+C(I,​J):​NEXT:​D(J)=D(J)+S:​S=INT((D(J)+S)/​CC):​D(J)=D(J)-INT(D(J)/​CC)*CC:​NEXT:​RETURN +
-run +
-Введите 1-й множитель +
-a=11111111111111111111111111111111111111111111111111111 +
-Введите 2-й множитель +
-b=10000000000000000000000000000000000000000000000000001 +
-a*b=11110001111000111100011110001111000 +
- ​111100011110001112111000111100011110001 +
- ​1110001111000111100011110001111 +
-Ok +
-</​code>​ +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-У попа была собака,​ он её любил.\\  +
-Она съела кусок мяса — он её убил!\\  +
-Убил и закопал,​ и надпись написал:​\\  +
-"У попа была собака,​ он её любил.\\  +
-Она съела кусок мяса — …" +
-<WRAP rightalign>​ +
-—//Из русского народного фольклора//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-Допустимо использование рекурсивных подпрограмм. +
- +
-//​Рекурсией//​ называется обращение подпрограммы (функции) к самой себе непосредственно или посредством других подпрограмм. Такие программы (функции) называются //​рекурсивными//​. Само слово "​рекурсия"​ означает "​возвращение"​ (лат. "​recursio"​). +
- +
-В программировании различают два типа рекурсии — рекурсивное определение или //​прямую//​ рекурсию и рекурсивное использование или //​косвенную//​ рекурсию. +
- +
-Рекурсивное использование — это способ описания процесса через подпроцессы,​ идентичные основному процессу,​ а рекурсивное определение — способ описания процесса через самого себя. +
- +
-Рекурсия получается в программах,​ реализующих алгоритмы,​ которые содержат //​рекуррентные//​ формулы,​ то есть формулы,​ в которых значение функции от некоторого аргумента X выражается через значение этой же функции,​ но от другого аргумента Y, который в каком–то смысле "​предшествует"​ X. +
- +
-Рекуррентной является,​ например,​формула вычисления факториала:​ +
- +
-<​code>​ +
-      ⎧         1, если k=1, +
-F(k)= ⎨ +
-      ⎩  F(k-1)·k, если k>1. +
-</​code>​ +
- +
- +
- +
-{{anchor:​e0441-11}} __//​Пример 1//__. Составим программу вычисления факториала натурального числа К, содержащую рекурсивную подпрограмму. +
-\\ {{.examples:​0441-11.bas|}} \\ [[+tab|wmsxbpge>​0441-11.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT K:F=1:GOSUB 100 '​──▶ +
-30 PRINT F:END +
-90 '​Внимание! Рекурсивная подпрограмма! +
-100 IF K>1 THEN F=F*K:​K=K-1:​GOSUB 100 '​──▶ +
-110 RETURN '​──▶ +
-run +
-? 4 +
- 24 +
-Ok +
- +
-run +
-? 6 +
-720 +
-Ok       +
- +
-run +
-? 48 +
-1.2413915592536E+61 +
-Ok +
- +
-run +
-? 49 +
-Overflow in 100 +
-Ok +
-</​code>​ +
-Конечно,​ любая рекурсивная подпрограмма может быть написана как циклическая программа. Например,​ последнюю программу можно переписать следующим образом:​ +
-<​code>​ +
-10 INPUT K:F=1  +
-20 IF K>1 THEN F=F*K:​K=K-1:​GOTO 20 +
-30 PRINT F:END  +
-</​code>​ +
-Но многим программистам больше нравится использование рекурсивных подпрограмм,​ несмотря на то, что коварство рекурсии проявляется в том, что бывает довольно трудно заметить дефект программы или алгоритма,​ а в циклическом процессе все на виду! +
- +
-{{anchor:​e0441-12}} __//​Пример 2//__. Пользуясь рекуррентной формулой +
-\\ <m>C matrix{2}{1}{0 n} = 1; C matrix{2}{1}{m n}={{n-m+1}/​m} * C matrix{2}{1}{{m-1} n}</​m>,​(∗) +
-\\ вычислить число сочетаний из <​m>​n</​m>​ по <​m>​m</​m>​ при <m>m, n=1, k, k>=1, m<​=n</​m>​. +
- +
-Приведём два варианта программы. +
-    * a) {{.examples:​0441-121.bas|}} \\ [[+tab|wmsxbpge>​0441-121.bas]] <​code>​ +
-10 INPUT K +
-20 FOR N=0 TO K:C=1:FOR M=1 TO N:IF M>N THEN NEXTN ELSE C=(N-M+1)/​M*C:​PRINT N;​M;​FIX(C+.5):​NEXT:​NEXT +
-run +
-? 3 +
-·1··1··1 +
-·2··1··2 +
-·2··2··1 +
-·3··1··3 +
-·3··2··3 +
-·3··3··1 +
-Ok +
-</​code>​ +
-  * b) {{.examples:​0441-122.bas|}} \\ [[+tab|wmsxbpge>​0441-122.bas]] <​code>​ +
-NEW +
-Ok +
-5 '​Программа находит число сочетаний из N по M по формуле (∗) с применением рекурсивной подпрограммы. +
-10 INPUT N,​M:​C=N:​GOSUB100:​PRINT FIX(C+.5):​END +
-100 IF M>1THEN C=C*(N-M+1)/​M:​M=M-1:​GOSUB100:​RETURN ELSE RETURN +
-run +
-? 232,231 +
-  232 +
-Ok +
- +
-run +
-? 233,232 +
- ​0 ​  ​◀── ?! +
-Ok             +
- +
-run +
-? 4080,4079 +
-Out of memory in 100 +
-Ok +
- +
-далее… +
-Ok +
-print m +
- 2 +
-Ok +
-</​code>​ +
- +
-{{anchor:​e0441-13}} __//​Пример 3//__ [[bibliography#​b6|[6]]]. +
-\\ {{.examples:​0441-131.bas|}} \\ [[+tab|wmsxbpge>​0441-131.bas]] +
-<​code>​ +
-NEW +
-Ok +
-100 INPUT "​Строка для сжатия:";​FS$ +
-109 '​Удаление пробелов из FS$. +
-110 S$=FS$:​RMV$="​ ":​GOSUB 200 +
-130 PRINT S$:END +
-140 '​∗∗∗∗ Рекурсивная подпрограмма сжатия строк. ∗∗∗∗ +
-150 'В RMV$ - удаляемые символы +
-160 'В S$ - исходная строка и результат +
-200 IF INSTR(1,​S$,​RMV$)<>​0 THEN S$=LEFT$(S$,​INSTR(1,​S$,​RMV$)-1)+RIGHT$(S$,​LEN(S$)-INSTR(1,​S$,​RMV$)):​GOSUB 200 +
-210 RETURN +
-</​code>​ +
-Сравните:​ +
-\\ {{.examples:​0441-132.bas|}} \\ [[+tab|wmsxbpge>​0441-132.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 INPUT"​Строка для сжатия:";​A$ +
-20 FOR I=1 TO LEN(A$):​C$=MID$(A$,​I,​1) +
-30 IF C$<>"​ " THEN B$=B$+C$ +
-40 NEXT:PRINT B$ +
-</​code>​ +
-Существует ограничение на число обращений подпрограммы к себе самой. Оно зависит от нескольких факторов,​ в частности от количества других вложенных одна в другую подпрограмм,​ выполняемых в этот же момент времени,​ и от размеров рабочего стека. +
- +
-Отметим,​ что понятие рекурсии охватывает также и весьма интересную ситуацию,​ при которой первая подпрограмма вызывает вторую,​ а та в свою очередь вызывает первую! +
- +
-{{anchor:​ongosub}} +
-===== IV.5. Оператор ON GOSUB ===== +
- +
-Кроме оператора перехода на подпрограмму в [[msx:​basic:​]] есть оператор выбора подпрограмм (оператор—"​переключатель"​). +
- +
-Его общий вид: +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-ON β GOSUB n1,​n2,​…nk +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​ON''​("​на"​),​ ''​GOSUB''​("​to GO to SUBroutine"​ — "​идти к подпрограмме"​) — служебные слова;​ +
-  * β — арифметическое выражение;​ +
-  * n1,​n2,​…,​nk — номера начальных строк подпрограмм. +
-Выполнение оператора ''​ON…GOSUB''​ начинается с вычисления целой части значения арифметического выражения β, которую мы обозначим p. +
- +
-Далее, если p ∈ {1,​2,​…,​k},​ где k — целое положительное число, то управление переходит к строке программы. +
- +
-Если p=0 или p>k, то выполняется оператор,​ следующий за ''​ON''​. После выполнения соответствующей подпрограммы управление передаётся оператору,​ расположенному за ''​ON GOSUB''​ . +
- +
-Если p<0, то компьютер выдаёт сообщение об ошибке:​ <WRAP centeralign>"​Illegal function call"​.</​WRAP>​ +
- +
-{{anchor:​e045-01}} __//​Пример 1//__. +
-\\ {{.examples:​045-01.bas|}} \\ [[+tab|wmsxbpge>​045-01.bas]] +
-<​code>​ +
-NEW +
-Ok +
-20 INPUT "​Ваш выбор (1-3)";​CH +
-27 ON CH GOSUB 31,​32,​33:​END +
-31 PRINT "​1":​RETURN'​ Попадаем сюда, если CH=1 +
-32 PRINT "​2"'​RETURN'​ Попадаем сюда, если CH=2 +
-33 PRINT "​3"'​RETURN'​ Попадаем сюда, если CH=3 +
-run +
-Ваш выбор (1-3)? 2 +
-+
-Ok +
-</​code>​ +
- +
-{{anchor:​e045-02}} __//​Пример 2//__. +
-\\ {{.examples:​045-02.bas|}} \\ [[+tab|wmsxbpge>​045-02.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 PRINT "​Draw,​Print,​Change,​Quit:";:​I$=INPUT$(1) +
-20 ON INSTR(2,"​ DdPpCcQq",​I$)/​2 GOSUB 100,​200,​300,​400 +
-30 PRINT:GOTO 10 +
-100 PRINT "​D":​RETURN '​──▶ +
-200 PRINT "​P":​RETURN '​──▶ +
-300 PRINT "​C":​RETURN '​──▶ +
-400 PRINT "​Q":​RETURN '​──▶ +
-run +
-Draw,​Print,​Change,​Quit:​█ +
-Draw,​Print,​Change,​Quit: ​    ​◀── нажата клавиша "​а"​ +
-Draw,​Print,​Change,​Quit:​Q ​   ◀── нажата клавиша "​q"​ +
-Draw,​Print,​Change,​Quit:​P ​   ◀── нажата клавиша "​p"​ +
-… +
-</​code>​ +
-Обратите внимание на примеры из раздела [[03#III.3. Оператор ON GOTO|III.3.]]! +
- +
-__//​Выводы //__ [[bibliography#​b8|[8]]]. При применении подпрограмм BASIC придерживайтесь следующих правил:​ +
-  - Чётко обозначайте начало и конец каждой подпрограммы. Если это возможно,​ выделяйте их путём отступа операторов вправо. +
-  - Никогда не пользуйтесь оператором ''​GOTO''​ для входа в подпрограмму и для выхода из неё. Каждую подпрограмму надо рассматривать как независимый логически завершённый //​модуль//​. +
-  - Имейте под рукой список глобальных входных переменных и выходных результатов каждой подпрограммы. Лучше всего оформить его комментариями к программе с помощью операторов ''​REM''​. +
-  - Обязательно убедитесь,​ что в подпрограмме не изменяются значения таких внешних переменных,​ как счётчики циклов. Если это возможно,​ в каждой подпрограмме вводите свой принцип именования внутренних переменных. +
-  - В отличии от функций,​ подпрограммы не появляются в программе до того, как ими будут пользоваться,​ поэтому полезно группировать подпрограммы вместе после оператора ''​END'',​ указанного в конце основной программы. +
- +
-===== IV.6. Дополнение 1 [77] ===== +
- +
-[[bibliography#​b77|[77]]] +
- +
-{{anchor:​e046-01}} +
-Программа позволяет умножить два числа, причём каждое из них может иметь "//​любое//"​ количество цифр при следующих ограничениях:​ в произведении должно содержаться не более 765 цифр и длина каждого из чисел должна быть ограничена возможной длиной строки. +
- +
-В заключение отметим,​ что приведённая программа работает неправильно либо когда одно из введённых чисел меньше 10, либо когда их произведение меньше 1000. Безусловно имеет смысл сделать программу "​защищённой"​ в этом отношении! +
-\\ {{.examples:​046-01.bas|}} \\ [[+tab|wmsxbpge>​046-01.bas]] +
-<​code>​ +
-5  CLEAR 1000 +
-10 DIM A(255),​B(255),​C(255) +
-20 T=1000:​Z$="​000"​ +
-30 PRINT"​Точное произведение целых чисел"​ +
-40 INPUT"​Введите первое число: ";A$ +
-50 LA=LEN(A$):​NA=INT((LA-1)/​3) +
-60 FOR I=0 TO NA-1 +
-70    A(I)=VAL(MID$(A$,​LA-2-3*I,​3)) +
-80 NEXT I +
-90 A(NA)=VAL(LEFT$(A$,​LA-3*NA)) +
-100 INPUT"​Введите второе число: ";B$ +
-110 LB=LEN(B$):​NB=INT((LB-1)/​3) +
-120 FOR I=0 TO NB-1 +
-130    B(I)=VAL(MID$(B$,​LB-2-3*I,​3)) +
-140 NEXT I +
-150 B(NB)=VAL(LEFT$(B$,​LB-3*NB)) +
-160 NC=NA+NB+1 +
-170 FOR I=0 TO NC:​C(I)=0:​NEXT I +
-180 FOR I=0 TO NA +
-190    FOR J=0 TO NB +
-200       ​K=I+J:​X=A(I)*B(J)+C(K) +
-210       ​Y=INT(X/​T):​C(K)=X-T*Y +
-220       IF Y>0 THEN K=K+1:​X=Y+C(K):​GOTO 210 +
-230    NEXT J +
-240 NEXT I +
-250 PRINT "​Произведение = "; +
-260 IF C(NC)=0 THEN NC=NC-1 +
-270 PRINT C(NC) +
-280 FOR I=NC-1 TO 0 STEP -1 +
-290    PRINT",";​RIGHT$(Z$+STR$(C(I)),​3);​ +
-300 NEXT I +
-320 END +
-run +
-Точное произведение целых чисел +
-Введите первое число: 12345678 +
-Введите второе число: 987654321 +
-Произведение =  12,​193,​262,​222,​374,​638 +
-Оk +
-print 12345678*987654321 +
- ​1.2193262222375E+16 +
-Ok +
-run +
-Точное произведение целых чисел +
-Введите первое число: 11111111111111111111 +
-Введите второе число: 6666666666666666666666666666666666666666 +
-Произведение =  74, 74, 74, 74, 74, 74, 73,​333,​333,​333,​333,​333,​333,​325,​925,​925,​925,​925,​925,​926 +
-Ok +
-print 11111111111111111111*6666666666666666666666666666666666666666 +
- ​7.4074074074074E+58 +
-Ok +
-</​code>​ +
-===== IV.7. Дополнение 2 [90] ===== +
- +
-[[bibliography#​b90|[90]]] +
- +
-{{anchor:​e047-01}} +
- +
-Нахождение факториалов "​огромных"​ чисел. +
-\\ {{.examples:​047-01.bas|}} \\ [[+tab|wmsxbpge>​047-01.bas]] +
-<​code>​ +
-10 DIM A(100):​PRINT"​Введите число N":​INPUT N:​A(1)=1:​J=1 +
-60 FOR I=2 TO N +
-80    P=0 +
-90    FOR K=1 TO J +
-100      C=A(K)*I+P:​P=INT(C/​10):​A(K)=C-P*10 +
-130   NEXT K +
-140   IF P=0 GOTO 200 +
-150   ​J=J+1 +
-160   IF J>100 THEN PRINT"​Не хватает места в массиве":​STOP +
-170   ​A(J)=P-INT(P/​10)*10:​P=INT(P/​10) +
-190   GOTO 140 +
-200 NEXT I +
-210 PRINT STR$(N);"​!=";​ +
-220 FOR K=J TO 1 STEP -1:PRINT RIGHT$(STR$(A(K)),​1);:​NEXT K +
-run +
-Введите число N +
-? 23 +
- ​23!=25852016738884976640000 +
-Ok +
-run +
-Введите число N +
-? 50 +
- ​50!=30414093201713378043612608166064768844377641568960512000000000000 +
-Ok +
-</​code>​ +
- +
-====== Диск с примерами ====== +
- +
-{{.examples:​examples04.dsk|Загрузить образ диска}} +
- +
-[[+tab|wmsxbpged>​examples04.dsk|Открыть диск в WebMSX]] +
- +
- +
----- +
- +
-[<>​] +
- +
- +
-{{tag>​MSX BASIC Book_msxbpg}}+
msx/basic_programming_guide/04.1584820312.txt.gz · Последние изменения: 2020-03-21 22:51 (внешнее изменение)