Здесь показаны различия между двумя версиями данной страницы.
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)) | + | |
- | 3 | + | |
- | Ok | + | |
- | </code> | + | |
- | * 6) <code>Ok | + | |
- | ? LEN(STR$(-56.20)) | + | |
- | 5 | + | |
- | Ok | + | |
- | </code> | + | |
- | * 7)<code> | + | |
- | Оk | + | |
- | ? LEN(STR$(-5620)) | + | |
- | 5 | + | |
- | Ok | + | |
- | </code> | + | |
- | * 8)<code> | + | |
- | Ok | + | |
- | ? LEN(STR$(1.2E-27) | + | |
- | 8 | + | |
- | 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) | + | |
- | 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 | + | |
- | 4 | + | |
- | 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 | + | |
- | 1 | + | |
- | 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 | + | |
- | 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}} | + |