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

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


msx:basic_programming_guide:09

Различия

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

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

msx:basic_programming_guide:09 [2020-04-01 15:18]
msx:basic_programming_guide:09 [2022-09-09 23:27] (текущий)
Строка 1: Строка 1:
-[<>​] +~~HIDEPAGE:​search;​sitemap~~ 
-~~TOC wide~~ +~~REDIRECT>msx:basic_dialogue_programming_language:009~~
- +
-====== Глава IX. Файловые средства MSX BASIC ====== +
- +
-<WRAP group  99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-//​Файл//​ (от англ. file — досье, картотека),​ набор данных,​— \\ +
-1) совокупность упорядоченных и взаимосвязанных записей,​ имеющая описание для идентификации отдельных записей;​ \\ +
-2) последовательность записей,​ размещаемая на внешних запоминающих устройствах (внешней памяти) и рассматриваемая в процессе пересылки и обработки как единое целое. +
-<WRAP rightalign>​ +
-—//​Математический Энциклопедический Словарь//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-В персональных компьютерах [[msx:yamaha_kuvt|]] предусмотрена работа с двумя версиями языка BASIC[[msx:​basic:​]] и [[msx:​disk_basic]]. Версия языка [[msx:​basic:​]] предусматривает работу только с накопителем на магнитной ленте, а в версии [[msx:​disk_basic]] возможно работать как с накопителем на магнитной ленте, так и с магнитными дисками. +
- +
-Выбор версии языка BASIC, с которой будет работать персональный компьютер [[msx:​yamaha_kuvt|]],​ осуществляется автоматически и зависит от состава подключённых внешних устройств хранения информации. +
- +
-Версия языка [[msx:​basic:​]] "​прошита"​ (записана,​ хранится) непосредственно в ПЗУ компьютера,​ а версия языка [[msx:​disk_basic]] записана и хранится в ПЗУ интерфейса (устройства сопряжения и согласования) дискового накопителя — //​дисковода//​. В зависимости от того, подключён ли интерфейс (вместе с дисководом) к компьютеру или нет, и выбирается версия языка BASIC, с которой мы будем работать. Если интерфейс подключён,​ то при включении компьютера "​работает"​ интерпретатор языка [[msx:​disk_basic]],​ а если нет, то "​включается"​ интерпретатор языка [[msx:​basic:​]]. +
- +
-<WRAP centeralign>​Практически для учительского компьютера это делается следующим образом:​ нажмите кнопку <​key>​Reset</​key>​ и в момент начальной инициализации компьютера держите нажатой клавишу <​key>​SHIFT</​key>​ !</​WRAP>​ +
- +
-Будем предполагать,​ что Ваш компьютер имеет встроенный дисковод. В таком варианте при включении запускается [[msx:​disk_basic]],​ а приоритетным устройством внешней памяти является дисковод ''​А:''​. +
- +
-Работая на компьютере без дисковода,​ Вы запускаете при включении [[msx:​basic:​]],​ а приоритетным устройством является кассетный магнитофон (''​CAS:''​),​ имя которого может опускаться. +
- +
-//​Замечание//​. \\ +
-В СССР распространены две версии языка [[msx:​basic:​]]:​ +
-  * версия 1.0 — на компьютерах серии [[msx:​msx_1]]:​ +
-    * [[msx:​yamaha_yis-503iir:​yamaha_yis-503iir|]] +
-  * версия 1.1 — на компьютерах серии [[msx:​msx_2]]:​ +
-    * [[msx:​yamaha_yis-503iiir:​yamaha_yis-503iiir|]] +
-    * [[msx:​yamaha_yis-805-128r2:​yamaha_yis-805-128r2|]] +
-Для определения номера версии в Вашей программе проверьте содержимое ячейки ПЗУ с адресом &​H002D:​ +
-<​code>​ +
-? PEEK(&​H002D) +
-</​code>​ +
- +
-^  Номер версии ​ ^  Содержимое ячейки ​ ^ +
-|  1.0  |  0  | +
-|  2.1  |  1  | +
- +
-===== IX.1. Работа с файлами на дискетах ===== +
- +
-Под словом //"​данные"//​ мы будем подразумевать содержимое памяти компьютера. Принято различать текст программы,​ исходные данные для работы программы и результаты работы программы. +
- +
-Работа с внешней памятью подразумевает запись и чтение данных,​ размещаемых на внешних носителях информации — кассете магнитной ленты или гибком магнитном диске (//​дискете//​). +
- +
-==== IX.1.1. Форматирование дискеты ==== +
- +
-Дискеты бывают следующих типов:​ +
-  - односторонние одинарной плотности (SS, SD); +
-  - односторонние двойной плотности (SS, DD); +
-  - двусторонние двойной плотности (DS, DD). +
- +
-Односторонность и двусторонность свидетельствует о том, имеет ли дисковод одну или две магнитные головки,​ которые обеспечивают запись и считывание информации с одной или двух сторон гибкого диска. Лучший способ объяснить понятие "​плотность записи"​ — провести аналогию с грампластинкой:​ считать,​ например,​ что на диске двойной плотности в два раза больше "​дорожек",​ чем на диске одинарной плотности. И хотя память на гибком диске является магнитной и никаких,​ естественно,​ дорожек нет, на гибком диске четверной плотности может храниться в четыре раза больше информации,​ чем на диске одинарной плотности. +
- +
-Для работы с 3,​5–дюймовым (8,89 см) дисководом MSX–компьютера используются односторонние дискеты MF1–DD, двусторонние дискеты MF2–DD или их аналоги (слова:​ "​диск",​ "​дискета"​ и "​флоппи–диск"​ мы будем рассматривать как синонимы). +
- +
-Дискета заключена в твёрдый пластмассовый конверт и имеет переключатель защиты записи и скользящую шторку для прикрытия окна, через которое организуется чтение (запись) информации. +
- +
-<WRAP centeralign>​Вставлять дискету в карман (щель) дисковода и извлекать её оттуда можно лишь при //​включённом//​ дисководе!</​WRAP>​ +
-{{anchor:​mf2dd}} +
-Приведём некоторые характеристики дискеты MF2–DD : +
-|Ёмкость при записи|| +
-|всего|720 Кбайт| +
-|для файлов пользователя|713 Кбайт| +
-|Плотность при записи|8717 бит/​дюйм| +
-|Среднее время доступа|95 мс| +
-|Максимальное количество файлов|112| +
- +
-Разрешается подключать к компьютеру как одиночные,​ так и спаренные дисководы. В первом случае за устройством закрепляется переменное имя, которое в любой момент времени принимает одно из конкретных значений "​А"​ или "​В"​. Во втором случае основной дисковод получает имя "​А",​ а дополнительный — "​В"​. +
- +
-Везде ниже, если это не оговорено специально,​ изложение ориентировано на использование одного дисковода. +
- +
-{{anchor:​callformat}} +
-Для подготовки диска к работе с командами и функциями [[msx:​disk_basic]] необходимо осуществить специальную разметку его поверхности,​ называемую //​форматированием//​. Для этого дискета вставляется в карман дисковода и выполняется команда:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-CALL FORMAT +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
- +
-</​WRAP>​ +
-</​WRAP>​ +
-или +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-_FORMAT +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-которая вызывает на экране индикацию запроса:​ +
-<​code>​ +
-Drive name? (A,B) █ +
-</​code>​ +
-Ответом на него должен быть ввод одной из латинских букв А или В, в зависимости от имени устройства,​ в котором находится дискета. +
- +
-На появившийся второй запрос–"​подсказку":​ +
-<​code>​ +
-1 - Double sided +
-2 - Single sided +
-? █ +
-</​code>​ +
-пользователь обязан отреагировать вводом 1, если диск — двусторонний,​ или 2, если диск — односторонний. +
- +
-Далее, по указанию:​ +
-<​code>​ +
-Strike a key when ready █ +
-</​code>​ +
-нажмите любую клавишу. После этого начинается процесс форматирования,​ то есть размещение на диске управляющих меток. При этом ранее имевшаяся там информация разрушается. Правильное завершение этого процесса вызывает индикацию сообщения +
-<​code>​ +
-Format complete +
-Ok +
-█ +
-</​code>​ +
-<WRAP centeralign>​Форматирование //​новых//​ дискет обязательно!</​WRAP>​ +
- +
-Учтите,​ что именно проведённая разметка дискеты,​ а не её потенциальные возможности определяет объем информации,​ который она может хранить,​ и с каким дисководом её можно использовать! +
- +
-В заключении дадим несколько //​полезных советов//:​ +
-  - В дискетах не предусмотрена идеальная защита записанных на них данных:​ защитные конверты рассчитаны только на предохранение поверхности носителей от повреждений на коротком пути от "​дискотеки"​ до дисковода. \\ Особую осторожность надо соблюдать при нанесении надписей на наклейке,​ прикреплённой к дискете,​ так как даже давление карандаша или шариковой ручки может оказаться достаточным,​ чтобы через защитный конверт повредить магнитный слой дискеты. Во избежании порчи информации,​ записанной на дискетах,​ последние следует хранить подальше от телевизоров,​ видео–мониторов,​ телефонов и других источников магнитных полей;​ +
-  - Для защиты файлов,​ сохранённых на дискете,​ позаботьтесь о создании копий файлов на другой дискете или на магнитной ленте;​ +
-  - Создайте архив файлов программных текстов и снабжайте дискеты и магнитные ленты архива этикетками;​ +
-  - Защищайте Ваши программы от неосторожного обращения путём установки переключателя защиты от записи на дискете. +
- +
-==== IX.1.2. Имена файлов ==== +
- +
-При создании на дискете нового файла ему необходимо присвоить определённое //имя//. Оно должно быть уникальным,​ то есть не совпадать ни с одним из уже имеющихся имён файлов,​ сформированных на данной дискете ранее. +
- +
-Имя служит для идентификации файлов и строится из последовательности символов алфавита [[msx:​basic:​]]. При этом должны учитываться следующие обстоятельства:​ +
-  - Количество символов имени не может превосходить 11. Попытка сформировать имя большей длины ни к чему не приводит. Правые лишние символы отбрасываются;​ +
-  - Соответствующие прописные и строчные латинские буквы, используемые в имени, равнозначны;​ соответствующие прописные и строчные буквы русского алфавита,​ используемые в имени, //​неравнозначны//;​ +
-  - В имени не должно быть символов:<​code>​ +
-;  ,  +  " ​ =  [  ]  *  \  /  ?  пробел +
-</​code>​ +
-  - Символ ":"​ используется только при задании составных имён для разделения их на две части, первая из которых есть имя ​ устройства, ​ а вторая — имя файла. В этом случае при записи файла на диск фиксируется лишь вторая часть имени;​ +
-  - Нельзя задавать имя, состоящее из одних пробелов или начинающееся с пробела;​ +
-  - Имя не должно начинаться с точки ("​."​). В нем не может быть более одного такого символа и более 8 символов перед ним (если их больше восьми,​ то после восьмого символа устанавливается "​."​). +
- +
-Кроме того, десятичной точкой имя можно разделить на две зоны: //​корень//​ (до точки) и //​расширение//​ (после точки). Расширение состоит не более, чем из трёх символов. Номер начальной позиции корня — 1, а расширения — 10. +
- +
-Если пользователь фиксирует имя без расширения с количеством символов,​ большим 8, то компьютер автоматически разбивает его на корень и расширение,​ вставляя в требуемое место точку. +
-Сообщение об ошибке <WRAP centeralign>"​Bad file name" (//"​Недопустимое имя файла"//​)</​WRAP>​ появляется в том случае,​ когда имя файла содержит более //​восьми//​ символов перед явно указанным расширением;​ если же расширение состоит более, чем из //​трёх//​ символов,​ то интерпретатор игнорирует лишние символы. +
- +
-__//​Примеры//​__. +
-^  Имя, заданное пользователем ​ ^  Представление имени в компьютере ​ ^ +
-|       ​КАТАЛОГ|КАТАЛОГ ​      | +
-|    LESSON.123|LESSON ​ .123  | +
-|         ​BASIC|BASIC ​        | +
-|   ​ВАЛ.процент|ВАЛ ​    ​.про ​ | +
-|   ​ПРОТИВОГАЗ |ПРОТИВОГ.АЗ ​  | +
- +
-Общепринято,​ что расширение имени файла должно обозначать его тип. Обычно применяются следующие стандартные расширения имён: +
- +
-^  Расширение ​ ^  Комментарий ​ ^ +
-|  .ASM  |Исходная программа на языке ассемблера| +
-|  .BAK  |Резервный файл или копия некоторого файла, сделанная на случай повреждения оригинала| +
-|  .BAS  |Программа на языке BASIC| +
-|  .BAT  |Командный файл для пакетной обработки| +
-|  .C  |Исходная программа на языке C| +
-|  .COM  |Команда или программа,​ пригодные для непосредственного исполнения под управлением DOS| +
-|  .DAT  |Файл данных| +
-|  .DOC  |Файл документов (для текстовой обработки)| +
-|  .FOR  |Исходная программа на языке Фортран| +
-|  .LIB  |Библиотека программ| +
-|  .OBJ  |Скомпилированная объектная программа на машинном языке| +
-|  .PAS  |Исходная программа на языке Паскаль| +
-|  .PIC  |Данные выводимого на экран изображения| +
-|  .TMP  |Временный файл| +
-|  .TXT  |Текстовый файл| +
- +
-//​Маленькая хитрость//​. Оградить Ваш файл от посторонних взглядов можно, дав ему секретное имя AAAAAAAA.AAA , например. Секрет здесь в том, что в этом имени часть букв A из русского,​ а часть — из латинского алфавита,​ и об этом знает только хозяин файла. +
- +
-В большинстве случаев желательно,​ чтобы присвоенные файлам имена были индивидуальными и единственными и точно указывали,​ какой именно файл имеется в виду. Но иногда удобнее обратиться сразу ко всей группе файлов,​ а не работать с ними по одному. +
- +
-Для указания //​родовых//​ имён файлов могут использоваться специально предназначенные для этого знаки ? и *. //​Вопросительный//​ знак является единственным неоднозначно интерпретированным символом в имени файла. Например,​ имена  +
-  * MAX1.ASM +
-  * MAX2.ASM  +
-  * MAX3.ASM +
-все соответствуют родовому имени файла MAX?.ASM, но ему не соответствует имя MAX10.ASM. +
- +
-//​Звёздочка//​ обозначает любое количество неоднозначно интерпретируемых символов. Например,​ Zilog*.A* будет обозначать любое имя файла, которое начинается с Zilog, при условии,​ что его расширение начинается с A. +
-\\ Однако звёздочка имеет смысл только при использовании её в качестве последнего символа имени файла или расширения. Например,​ родовое имя файла *CALC.BAS — это то же самое, что и имя *.BAS, которое соответствует каждому файлу, имеющему расширение имени *.BAS. +
- +
-Отметим,​ что *.* — родовое имя файлов с любыми именами. +
- +
-{{anchor:​autoexecbas}} +
-=== AUTOEXEC.BAS === +
- +
-Имя файла ''​AUTOEXEC.BAS''​ происходит от Automatic Execution ("​автоматическое исполнение"​). Файл с таким именем будет автоматически загружен и запущен.  +
- +
-''​AUTOEXEC.BAS''​ это Программа на языке BASIC, это файл можно использовать например,​ для выполнения инициализации ​ (подготовки компьютера к работе). Подробно об этом процессе написано в разделе:​  +
-[[msx:​basic_programming_guide/​07#​VII.3. Инициализация в языке MSX BASIC]]. +
- +
-Пример [[msx:​basic_programming_guide:​07#​fk-bas|установки новых значений функциональных клавиш]] через {{.examples:​autoexec.bas|}} \\ [[+tab|wmsxbpge>​autoexec.bas]] +
- +
----- +
- +
-Добавлено 2019-10-17 (примечание редактора) +
- +
-==== IX.1.3. Справочная информация о файлах ==== +
- +
-<WRAP group  99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Старейшим из дошедших до нас каталогов признается список литературных произведений на шумерской глиняной плитке,​ относящейся к 2000 г. до н.э.. +
-<WRAP rightalign>​ +
-—//​А.И.Михайлов//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-{{anchor:​files}} +
-Сейчас мы расскажем Вам о довольно простых средствах для получения списка имён файлов,​ размещённых на дискете (''​FILES''​),​ размера её свободной части (''​[[#​DSKF]]''​) и некоторой другой справочной информации. +
- +
-Вывод имён файлов осуществляется по команде (оператору!) +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-[L]FILES [I] +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​FILES'',​ ''​LFILES''​ ("​файлы"​) — служебные слова;​ +
-  * I — строковое выражение,​ значение которого определяет имя файла или родовое имя файлов. +
-При выполнении этой команды без параметра I список имён всех файлов диска или отображается на экране (если префикс ''​L''​ отсутствует),​ или распечатывается принтером (префикс ''​L''​ есть). В зависимости от типа экрана и его ширины индикация имён организуется в несколько колонок. Вывод списка файлов на печать проводится в 1 колонку:​ каждому имени отводится одна строка. При отсутствии файлов на диске выдаётся сообщение:​ <WRAP centeralign>"​File not found" (//"​Файл не найден"//​).</​WRAP>​ +
- +
-Если параметр I указан и на диске имеется файл с этим именем,​ то данный факт подтверждается выводом единственного имени I (в противном случае Вы прочтёте неприятное сообщение:​ "File not found"​). +
- +
-Для указания диска добавляется имя диска ''​A:'',​ ''​B:'',​ и т.д. +
- +
-__//​Примеры//​__. +
-<​code>​ +
-FILES +
- +
-100 FILES +
- +
-FILES "​Игры"​ +
- +
-LFILES +
- +
-FILES "​B:"​ +
-</​code>​ +
- +
-{{anchor:​dskf}} +
-Функция ''​DSKF()'':​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-DSKF(n) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​DSKF''​("​DiSK Free" — "​свободная часть диска"​) — служебное слово;​ +
-  * <​WRAP>​n — арифметическое выражение,​ целая часть значения которого должна принадлежать отрезку [0,8], возвращает размер в Килобайт свободной части диска. Целая часть значения n определяет имя диска:​ +
-^  Значение ​ ^  Имя диска ​ ^ +
-|  0  |  Текущий ​ | +
-|  1  |  A  | +
-|  2  |  B  | +
-|  3  |  C  | +
-|  4  |  D  | +
-|  5  |  E  | +
-|  6  |  F  | +
-|  7  |  G  |  +
-|  8  |  H  | +
-</​WRAP>​ +
- +
-__//​Примеры//​__. +
-<​code>​ +
-PRINT DSKF(0):​PRINT DSKF(1):​PRINT DSKF(2) +
- +
-X=1:PRINT DSKF(X) +
- +
-IF DSKF(0)>​200 THEN 1000 +
-</​code>​ +
- +
-Забегая далеко вперёд,​ заметим,​ что для определения размера в байтах области дискеты,​ отведённой под произвольный файл, можно воспользоваться командами:​ +
-<​code>​ +
-OPEN "​Имя файла"​ FOR INPUT AS#1:PRINT LOF(1):​CLOSE #1 +
-</​code>​ +
- +
-{{anchor:​dski}} +
-FIXME Функция ''​DSKI$()''​ [[bibliography#​b92|[92]]] +
- +
-{{anchor:​dsko}} +
-FIXME Функция ''​DSKO$''​ [[bibliography#​b92|[92]]] +
- +
-==== IX.1.4. Операторы NAME, COPY и KILL ==== +
- +
-{{anchor:​name}} +
-Изменение имени программного файла или файла данных производится по команде (оператору) +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-NAME I AS J +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​NAME''​ ("​имя"​) — служебное слово,​ +
-  * I — строковое выражение,​ значение которого определяет "​старое"​ имя файла,​ +
-  * J — строковое выражение,​ значение которого определяет "​новое"​ имя файла. +
-При выполнении этой команды прерывание происходит при отсутствии на дискете файла с именем I (нечего переименовывать!),​ при наличии на ней файла с именем J (имя J уже зарезервировано!) или при закрытой на запись +
-дискете. +
- +
-В противном случае файл с именем I получает новое имя J. +
- +
-При задании имени J разрешено использование символов "?"​. Но при реальном формировании имени J на дискете каждый такой символ будет заменён на элемент из соответствующей позиции имени I. +
- +
-__//​Примеры//​__. +
-<​code>​ +
-NAME "​алфавит"​ AS "​АЛФ"​ +
- +
-name X$ as "​X.1"​ +
- +
-200 NAME "​PQR.XYZ"​ AS "?​.?​11"​ +
-</​code>​ +
-В последнем случае новое имя будет выглядеть так: +
-<​code>​ +
-  Р   ​▲ ​  ​.Х11 +
-      │ +
- 7 пробелов +
-</​code>​ +
- +
-{{anchor:​copy}} +
-Для дублирования на дисках программных файлов и файлов данных применяется команда (оператор) +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-COPY i TO j +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​COPY''​ ("​копировать"​),​ ТО("​в"​) — служебные слова;​ +
-  * i — строковое выражение,​ значение которого определяет имя исходного файла;​ +
-  * j — строковое выражение,​ значение которого определяет имя формируемого файла. +
- +
-При выполнении команды (оператора) COPY по файлу любого формата с именем i создаётся его копия с именем j. Имена i и j не должны совпадать. В том случае,​ когда файл с именем j уже существует на дискете,​ содержимое +
-файла с именем j заменяется на содержимое файла с именем i и, естественно,​ "​старое"​ содержимое файла с именем j пропадает! +
- +
-Если i или j — файлы данных,​ то они не должны быть открыты! +
- +
-__//​Примеры//​__. +
-1) +
-<​code>​ +
-COPY "​AL"​ TO "​LA"​ +
-</​code>​ +
-2) +
-<​code>​ +
-COPY "​X"​ TO "​X.1"​ +
-</​code>​ +
-3) +
-<​code>​ +
-10 SAVE "​U.1"​ +
-20 FOR J=1 TO 20 +
-30 COPY"​U.1"​TO"​U."​+MID$(STR$(J),​2) +
-40 NEXT +
-</​code>​ +
-4) +
-<​code>​ +
-COPY "​A:​ПРОБА"​ ТО "​В:​ПРОБА"​ +
-</​code>​ +
- +
-Копирование всех файлов с одной дискеты на другую при наличии нескольких (больше двух) дисководов проводится операторами:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-COPY "​A:​*.*"​ TO "​B:​*.*"​ +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-(с А на В) +
-</​WRAP>​ +
-</​WRAP>​ +
- +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-COPY "​B:​*.*"​ TO "​A:​*.*"​ +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-(с В на А) +
-</​WRAP>​ +
-</​WRAP>​ +
- +
-На одном дисководе эта процедура и ей подобные (см.пример 4) реализуются по соответствующим сообщениям на экране периодической сменой дискет в кармане дисковода. +
- +
-Если служебное слово ''​ТО''​ и второй аргумент будут опущены,​ то файл будет скопирован на активный дисковод (обычно с B: на A:), например:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-COPY"​b:​E87.COM"​ +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-{{anchor:​kill}} +
-По команде (оператору) +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-KILL I +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​KILL''​ ("​разрушать",​ "​убивать"​) — служебное слово;​ +
-  * I — строковое выражение,​ значение которого определяет имя файла, происходит разрушение на дискете файла с именем I и увеличение на соответствующую величину размера свободной части дискеты. Фактическому разрушению (стиранию) подвергается лишь справочная информация о файле. +
- +
-Если I — имя файла данных,​ то при выполнении команды ''​KILL''​ он не должен быть открыт. +
- +
-__//​Примеры//​__. +
-<​code>​ +
-KILL"​Бочка":​KILL"​R.T"​ +
- +
-X$="​ЮюЮ":​KILL X$ +
- +
-100 FOR K=1 TO 25:​KILL"​ЦЕХ."​+MID$(STR$(K),​2):​NEXT +
-</​code>​ +
- +
-==== IX.1.5. Операторы LOAD, SAVE, RUN и MERGE ==== +
- +
-{{anchor:​save}} +
-По команде (оператору):​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-SAVE I [,A] +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​SAVE''​ ("​сохранить"​) — служебное слово;​ +
-  * I — строковое выражение,​ значение которого определяет имя файла, программа из оперативной памяти под именем I записывается на дискету. В зависимости от наличия или отсутствия параметра А запись проводится соответственно или в формате ASCII, или в форме внутреннего представления (см. [[202|]]). +
- +
-Попробуем прочесть программу +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-10 X=1 +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-записанную:​ +
- +
-  * в кодах ASCII: <​code>​10 X=1</​code>​ +
-  * во внутреннем представлении (по кодам, см. [[202|]]): <​code>​ +
-          FF   ​09 ​  ​80 ​  ​0A ​  ​00 ​  ​58 ​  ​EF ​  ​12 ​  ​00 ​  ​00 ​  00 +
-          ── ​  ​───▲─── ​  ​───▲─── ​  ​── ​  ​▲ ​   ── ​  ​─▲ ​  ​───▲─── +
-  Начало ​ ▲       ​│ ​        ​│ ​      ​▲ ​  ​│ ​   ▲     ​│ ​     └  Конец +
-программы ┘ Адрес следу– ​ Номер ​    └ X =  1 ┘    Конец ​    ​программы +
-            ющей строки ​ строки (10)              строки +
-</​code>​ +
- +
-Если данная программа впоследствии будет погружаться в память для слияния с другими программными модулями,​ то её необходимо записывать в коде ASCII. +
- +
-Заметим что формат ASCII приводит к увеличению в несколько раз времени записи программ из оперативной памяти на дискету,​ а также их чтения с дискеты в память. К тому же для их размещения на дискете требуется приблизительно на 30% больше места, чем для соответствующих программ,​ написанных во внутреннем представлении (см. [[202|]]). +
- +
-При наличии на диске программного файла или файла данных с именем I и записи на него новой программы под тем же именем,​ старый файл пропадает и происходит изменение размера свободной части диска в соответствии с новыми размерами файла с именем I. +
- +
-__//​Примеры//​__. +
-<​code>​ +
-SAVE"​PROTOOL.SYS"​ +
- +
-X$="​Z80.ABC":​SAVE X$:​SAVE"​PRIMER.BAS",​A +
- +
-10 FOR M=1 TO 30:​SAVE"​палата"​+MID$(STR$(М),​2):​NEXT +
-</​code>​ +
-Для считывания программ с дискеты в оперативную память используются команды (операторы) ''​LOAD''​ и ''​RUN''​. +
- +
-  - <​WRAP>​ {{anchor:​load}} По команде +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-LOAD I[,R] +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​LOAD''​ ("​загрузка"​) — служебное слово;​ +
-  * I — строковое выражение,​ значение которого определяет имя файла;​ +
-  * R — необязательный параметр;​ +
-прежде всего закрываются все файлы и оперативная память очищается от программ и данных. Далее, программа,​ записанная на дискете в машинных кодах или формате ASCII под именем I, загружается в оперативную память. +
- +
-При наличии параметра R после загрузки производится запуск программы на счёт. +
- +
-__//​Примеры//​__. +
-<​code>​ +
-LOAD"​X.Y"​ +
- +
-Z$=MID$(A$,​5,​3):​LOAD Z$,R +
-</​code>​ +
- +
-<WRAP centeralign>​ +
-Ещё раз напомним Вам, что загрузка программы "​стирает"​ программу,​ находящуюся в момент загрузки в памяти компьютера. +
-</​WRAP>​ +
- +
-</​WRAP>​ +
- +
-  - <​WRAP>​ По команде {{anchor:​run}} +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-RUN I[,R] +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​RUN''​ ("​запуск",​ "​прогон"​) - служебное слово,​ +
-  * I — строковое выражение,​ значение которого определяет имя файла, в оперативную память загружается и запускается на счёт программа,​ записанная на диске под именем I в машинных кодах или в формате ASCII. +
- +
-При отсутствии параметра R перед загрузкой файла с именем I закрываются все открытые файлы и память очищается от программ и данных. +
- +
-При наличии параметра R из памяти удаляются программы и значения переменных. Однако файлы данных //не закрываются//​ ! +
-</​WRAP>​ +
- +
-{{anchor:​e0915-01}} __//​Пример//​__[[bibliography#​b5|[5]]]. \\ {{.examples:​0915-01.bas|}} \\ [[+tab|wmsxbpge>​0915-01.bas]] +
- +
-<​code>​ +
-1 '​Меню многомодульного файла "​MMF"​ +
-2 COLOR 1,​7,​13:​SCREEN 1:​PRINT:​PRINT TAB(7)"​Основное меню"​ +
-4 PRINT TAB(6)"​───────────────":​PRINT +
-6 PRINT"​1. программа A - 1":​PRINT"​2. программа B - 2" +
-8 PRINT"​3. программа С - 3":​PRINT"​4. программа Д - 4" +
-11 INPUT R:IF R<1 OR R>4 THEN 11 +
-13 ON R GOTO 14,​15,​16,​17 +
-14 RUN"​прог.А",​R +
-15 RUN"​прог.В",​R +
-16 RUN"​прог.С",​R +
-17 RUN"​прог.Д",​R +
-</​code>​ +
-Приведём вид отдельного модуля,​ например,​ модуля с именем "​прог.А":​ +
-<​code>​ +
-10 PRINT"​Выполняется программа А" +
-20 RUN"​ММF",​R +
-</​code>​ +
- +
-Интересные возможности по "​соединению"​ программ предоставляются командой (оператором!) +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-MERGE I +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​MERGE''​ ("​слияние"​) — служебное слово;​ +
-  * I — строковое выражение,​ определяющее имя файла, записанного на дискете в формате ASCII. +
- +
-<WRAP centeralign>​ +
-Выполнение команды ''​MERGE''​ начинается с закрытия всех файлов и чистки оперативной памяти от данных. +
-</​WRAP>​ +
- +
-Далее производится слияние программы А, находящейся в памяти,​ с программным файлом,​ записанным на диске в формате ASCII под именем I. +
- +
-__//​Примеры//​__ +
-<​code>​ +
-MERGE "​TTT"​ +
- +
-L$="​техника":​MERGE L$ +
- +
-100 MERGE "​LIST.3"​ +
-</​code>​ +
-Обратите внимание на тот факт, что программы,​ вызываемые командой ''​MERGE'',​ имеют более высокий приоритет,​ по сравнению с программами,​ находящимися в памяти компьютера. Поэтому если в объединяемых программах имеются строки с одинаковыми номерами,​ то строки программы в памяти компьютера будут заменены соответствующими строками "​добавляемой"​ программы с именем I. +
- +
-Наиболее целесообразно использовать этот оператор при работе с библиотеками подпрограмм на магнитной ленте или на дискете. Покажем,​ как это делается. +
- +
-__//​Пример//​__. +
- +
-Предположим,​ что программа,​ находящаяся в памяти,​ занимает строки с 10 по 1290. Для добавления подпрограммы,​ названной при записи на дискету "​ROUT1"​ и занимающей строки с 10 по 190, сначала Вы должны сохранить программу,​ находящуюся в памяти. +
- +
-После этого, Вы вызываете подпрограмму "​ROUT1",​ используя команды ''​LOAD''​ или ''​CLOAD''​. +
- +
-Теперь используйте команду ''​RENUM''​ для перенумерации строк подпрограммы,​ начиная,​ например,​ со строки 10000. +
- +
-Далее сохраните подпрограмму в формате ASCII, назвав её новым именем,​ например "​ROUT0",​ после чего повторно загрузите основную программу. +
- +
-Теперь выполнение команды +
-  MERGE "​ROUT0"​ +
-приведёт к тому, что в конце текста основной программы будет добавлен текст подпрограммы с номерами строк, начинающимися с 10000. +
- +
-===== IX.2. Файлы данных прямого доступа ===== +
- +
-<WRAP group  99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Я знаю, что положил это в надёжное место, но теперь не могу вспомнить,​ в какое именно! +
-<WRAP rightalign>​ +
-—//Из диалога на приёме у врача//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-Как мы уже отмечали (см. [[05|главу V]]), файл данных //​прямого//​ доступа представляет собой последовательность нумерованных групп значений,​ называемых //​записями//​. +
- +
-Запись представляет собой единицу хранимой в файле информации. Размер записи зависит от решаемой Вами задачи. Запись есть совокупность сведений о некотором объекте. Она образуется из //​полей//,​ или элементов данных,​ +
-указывающих на различные атрибуты,​ присущие конкретному объёму. +
- +
-Так, если "​объектами"​ для зубного врача являются пациенты,​ то каждая запись должна хранить информацию о каком–либо пациенте,​ а её полями могут быть имя пациента,​ его возраст,​ номер телефона и число поставленных пломб. +
- +
-На рисунке показано зрительное представление организации файла прямого доступа. Записи с данными хранятся на дискете. При каждом запросе программы на чтение или на запись должен быть указан //​номер записи//,​ по +
-которому во внутреннем справочнике находится её фактическое положение на дискете,​ что позволяет немедленно произвести чтение или запись. Таким образом осуществляется прямой доступ к записям,​ требующий примерно одного +
-и того же небольшого (зависящего от скорости вращения дискеты) времени для всех записей. +
-<​code>​ +
-            ┌──────────────────────────────┐ ​  ​┌──────────────────┐ +
-            │                              ◀───▶ Запись с данными │ +
-Запись ​     │ Внутренний справочник файла, │   ​└──────────────────┘ +
-────▶────◀──┤ связывающий номер записи ​ с  │            … +
-      Чтение│её физическим местонахождением│ ​  ​┌──────────────────┐ +
-            │                              ◀───▶ Запись с данными │ +
-            └──────────────────────────────┘ ​  ​└──────────────────┘ +
-</​code>​ +
- +
-Нумерация записей выполняется последовательно,​ начиная с нуля. В запись объединяются логически связанные между собой данные,​ и номер записи обычно связывается с этими данными естественным образом. +
- +
-Например,​ если записи содержат информацию о студентах некоторой группы,​ то в качестве номеров записей можно использовать номера студентов в списке группы. +
- +
-Во время выполнения операции //​вывода//​ для размещения записи будет выбрано место, определяемое её номером. При выполнении операции ввода по номеру отыскивается запись и передаётся в память. +
- +
-<WRAP centeralign>//​Прямой//​ доступ к файлу целесообразен в том случае,​ когда требуется часто менять содержимое записей и просматривать их в произвольном порядке.</​WRAP>​ +
- +
-Так, бронированные места в зале театра,​ меняющиеся от спектакля к спектаклю уместно хранить в файле прямого доступа. +
- +
-Вы, как программист,​ должны предусмотреть размещение каждого символа в файле прямого доступа. В этом есть смысл: можно определить структуру файла в соответствии с Вашими потребностями.Вы сами регулируете поток данных +
-в файле, и поэтому важно тщательно продумать его структуру. Разработка структуры файла не составит для Вас труда, если ясно представлять себе, что происходит в программе. +
- +
-Перейдём теперь к детальному описанию средств языка [[msx:​basic:​]],​ предназначенных для работы с файлами данных //​прямого//​ доступа. +
- +
-==== IX.2.1. Контрольные буферы файлов ==== +
- +
-{{anchor:​maxfiles}} +
-Оператор +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-MAXFILES=A +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где:  +
-  * ''​MAX'',​ ''​FILES''​ — служебные слова;​ +
-  * А — арифметическое выражение,​ целая часть значения которого принадлежит отрезку [0,15], резервирует А+1 участок оперативной памяти для последующего //​временного//​ хранения записей конкретных файлов. +
- +
-Например:​ +
-<​code>​ +
-10 MAXFILES=5 +
- +
-50 MAXFILES=X+Y +
- +
-MAXFILES=3 +
-</​code>​ +
-Эти участки называются //​буферами//​ или, более полно, //​контрольными буферами//​ файлов ("​Field Control Buffers"​ — FCB) и обозначаются:​ FCB 0, FCB 1,… . +
- +
-<WRAP centeralign>​Каждый FCB занимает 265 байтов,​ из которых 9 байтов предназначены для управляющей информации,​ а 256 байтов — для данных.</​WRAP>​ +
- +
-Следует иметь в виду, что FCB0 и FCB1 объявлены по умолчанию и что FCB0 используется многими операторами (''​SAVE'',​ ''​LOAD'',​ ''​MERGE'',​ ''​RUN''​ и т.п.). +
- +
-При выполнении оператора ''​MAXFILES=''​ кроме резервирования буферов производится "​чистка"​ значений переменных и закрытие всех ранее открытых файлов данных. +
- +
-При выполнении операции //​чтения//​ запись из файла помещается в контрольный буфер файла, а при выполнении операции вывода,​ наоборот,​ содержимое буфера переносится в файл, в область,​ отведённую для записи с указанным номером. +
- +
-После выполнения операции чтения данные необходимо выбирать из буфера файла, а перед выполнением операции //​вывода//​ данные должны быть помещены в буфер файла. +
- +
-{{anchor:​varptr}} +
-Функция +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-VARPTR(#​n) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где:  +
-  * ''​VARPTR''​ ("​VARiable PoinTeR"​ — "​указатель переменной"​) — служебное слово;​ +
-  * n — арифметическое выражение,​ целая часть значения которого определяет номер FCB (от 0 до значения выражения,​ стоящего в правой части оператора ''​MAXFILES=''​),​ возвращает //​адрес//​ X байта, начиная с которого расположен в памяти FCBn. +
- +
-Если файл не существует,​ то выдаётся сообщение об ошибке:​ <WRAP centeralign>"​Illegal function call"​.</​WRAP>​ +
- +
-{{anchor:​e0921-01}} Приведём простейший пример:​ +
-\\ {{.examples:​0921-01.bas|}} \\ [[+tab|wmsxbpge>​0921-01.bas]] +
-<​code>​ +
-10 MAXFILES=2:​X=VARPTR(#​0):​Y=VARPTR(#​1):​Z=VARPTR(#​2) +
-20 PRINT Y-X;Z-Y +
-run +
- ​265 ​ 265 +
-Ok +
-</​code>​ +
- +
-Взгляните на схему расположения информации в FCBn : +
-<​code>​ +
-Управляющая информация ────┐ ​       Данные ​           +
-                 ​┌───┬───┬─▼─┬───┬───┬───┬───┐ +
-                 ​│▧▧▧│▧▧▧│···│▧▧▧│███│···│███│ +
-                 ​└───┴───┴───┴───┴───┴───┴───┘ +
-      Адреса ──▶ ​  ​X ​ X+1     X+8 X+9    X+264 +
-                   ▲ +
-                   │ +
- ​Байт,​ адрес которого возвращает функция VARPTR(#​n) +
-</​code>​ +
- +
-//​Контрольный буфер файла//​ (FCB) +
-^  Номер байта ​ ^  Имя байта ​ ^  Содержимое байта ​ ^ +
-|X  |FL.MOD|Тип файла: \\ 1 — OPEN FOR INPUT \\ 2 — OPEN FOR OUTPUT \\ 2 — OPEN FOR APPEND (для диска) \\ 4 — файл прямого доступа (для диска) \\ 4 — файл последовательного доступа,​ открытый и для чтения,​ и для записи,​ например,​ <​code>​OPEN "​COM:"​ AS#​1</​code>​ \\ 8 — OPEN FOR APPEND (для устройства MEM:)| +
-|X+1|FL.FCA|Ссылка на область памяти,​ в которой хранится [[#​file_specification|спецификация файла]]| +
-|X+2|FL.LCA|:::​| +
-|X+3|FL.LSA| ​ ?  | +
-|X+4|FL.DSK|Номер текущего устройства:​ \\ 0 — активное устройство по умолчанию;​ \\ 1 — устройство A: \\ 2 — устройство B: \\ 3 — устройство C: \\ 4 — устройство D: \\ 5 — устройство E: \\ 6 — устройство F: \\ 7 — устройство G: \\ 8 — устройство H: \\ &hFC — устройство GRP: \\ &hFD — устройство CRT: \\ &hFE — устройство LPT: \\ &hFF — устройство CAS: \\ Нестандартные ​ устройства:​ \\ &hD4 — устройство COM: (локальная сеть [[msx:​msx_1]]) \\ &hC0 — устройство MEM:| +
-|X+5|FL.SLB| ​ ?  | +
-|X+6|FL.BPS| ​ ?  | +
-|X+7|FL.FLG| ​ ?  | +
-|X+8|FL.OPS| ​ ?  | +
-|X+9|FL.BUF|Содержимое записи файла (256 байт)| +
- +
-{{anchor:​file_specification}} //​Спецификация файла//​ +
-^  Номер байта ​ ^  Содержимое байтов ​ ^  Количество байт ​ ^ +
-|+00|Номер дисковода (0 — по умолчанию,​\\ 1 — A:)|  1  | +
-|+01|Имя файла| ​ 8  | +
-|…|:::​|:::​| +
-|+08|:::​|:::​| +
-|+09|Расширение имени файла| ​ 3  | +
-|+12|Номер текущего блока| ​ 2  | +
-|+14|Текущий размер записи (по умолчанию равен 128)|  2  | +
-|+16|Размер файла в байтах| ​ 4  | +
-|+20|Дата изменения файла| ​ 2  | +
-|+22|Время изменения файла| ​ 2  | +
-|+24|Идентификатор устройства| ​ 1  | +
-|+25|Расположение каталога| ​ 1  | +
-|+26|Первый кластер файла| ​ 2  | +
-|+28|Последний кластер файла| ​ 2  | +
-|+30|Последний доступный кластер (относительно начала файла)| ​ 2  | +
-|+32|Номер текущей записи файла последовательного доступа |  1  | +
-|+33|Номер случайной записи для файла прямого доступа (байты 33,34,35 — если размер записи больше 63; байты 33,34,35,36 — если размер записи меньше 64)|  4  | +
-|+34|:::​|:::​| +
-|+35|:::​|:::​| +
-|+36|:::​|:::​| +
- +
-==== IX.2.2. Операторы OPEN и CLOSE ==== +
- +
-Для работы с файлами данных,​уже существующими на дискетах или вновь организуемыми,​ необходимо произвести их //​открытие//​. Делается это оператором +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-OPEN B AS[#]n [LEN=m] +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​OPEN''​ ("​открыть"​),​ LEN("​LENgth"​ — "​длина"​) — служебные слова;​ +
-  * B — строковое выражение,​ значение которого определяет имя файла;​ +
-  * n, m — арифметические выражения,​ целые части значений которых определяют соответственно //​номер//​ контрольного буфера файла и //​длину//​ его записи в байтах;​ +
-    * целая часть значения n должна принадлежать отрезку [0,6], так как дисковод может одновременно работать только с //​семью//​ различными файлами;​ +
-    * целая часть значения m должна принадлежать отрезку [1,256] (по умолчанию значение m равно 256). +
-Все записи файла с //​прямым//​ доступом имеют одинаковую длину, которая (в байтах) задаётся параметром m . Это значение определяет способ разбиения на записи дискового пространства,​ отведённого для файла. +
- +
-Например,​ если длина записи равна 50,то 6–я запись будет располагаться со смещением 300 (50×6) от начала файла;​ +
-  * # — необязательный символ,​ никак не влияющий на выполнение оператора ''​OPEN''​ . +
- +
-При выполнении оператора ''​OPEN''​ файлу с именем В назначается для работы контрольный буфер с номером n. Кроме того: +
-  * с дискеты в буфер заносится управляющая информация о файле (если файл с именем B уже существует) или +
-  * эта информация создаётся на дискете (если файл с именем В формируется заново). +
- +
-<WRAP centeralign>​Вся эта процедура и называется //​открытием//​ файла.</​WRAP>​ +
- +
-Отметим,​ что один файл В не может быть открыт сразу по нескольким FCB!  +
- \\ Например:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-10 OPEN "​А"​ AS#1 +
-MAXFILES=2:​OPEN"​Старт"​AS#​2 +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-<​code>​ +
-90 OPEN "​klukva"​ AS#1 LEN=50 +
-MAXFILES=5:​OPEN"​Финиш"​AS#​3 LEN=100 +
-</​code>​ +
-</​WRAP>​ +
-</​WRAP>​ +
- +
-<WRAP centeralign>​Оператор ''​OPEN''​ открывает файл с //​прямым//​ доступом,​ если спецификации режимов ''​FOR INPUT'',​ ''​OUTPUT''​ или ''​APPEND''​ опущены.</​WRAP>​ +
- +
-Если программа закончит запись в файл, а в буфере останутся некоторые,​ не записанные на дискету данные,​ программа должна тем или иным способом все же завершить перепись содержимого буфера. Сделать это можно с помощью оператора //​закрытия//​ файла, к изучению которого мы и приступаем. +
- +
-Оператор +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-CLOSE [[#​]N1,​[#​]N2,​...,​[#​]Nk] +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​CLOSE''​ ("to close" — "​закрывать"​) — служебное слово;​ +
-  * N1,​N2,​...,​Nk — арифметические выражения,​ целые части значений которых должны принадлежать отрезку [0,15], +
-организует //​закрытие//​ открытых с помощью оператора ''​OPEN''​ файлов,​ имеющих номера контрольных буферов файлов,​ равных значениям выражений:​ N1, N2,…, Nk . +
- +
-Оператор ''​CLOSE''​ без параметров закрывает //все// открытые на данный момент файлы данных. +
- +
-Однако большинство программистов предпочитают иметь гарантированный точный результат работы оператора ''​CLOSE''​ и поэтому указывают в нем номера файлов в явном виде. +
- +
-//​Закрытый//​ файл становится недоступным для формирования новых или обновления оператором ''​PUT''​ уже имеющихся записей. +
- +
-Приведём примеры синтаксиса оператора ''​CLOSE''​ : +
-<​code>​ +
-CLOSE +
- +
-CLOSE #0 +
- +
-CLOSE 1.5,7 +
-</​code>​ +
- +
-<WRAP centeralign>​Заметим,​ что закрытие всех ранее открытых файлов происходит также при выполнении операторов ''​END'',​ ''​CLEAR'',​ ''​LOAD'',​ ''​MAXFILES='',​ ''​NEW''​ и любом //​изменении//​ текста программы !</​WRAP>​ +
- +
-Пока файл не закрыт,​ существует опасность,​ что прекращение работы программы — из–за ошибки пользователя,​ отключения электроэнергии или ошибки в программе — приведёт к утрате данных или даже к повреждению дискеты. +
-Опыт подсказывает,​ что желательно закрывать файл, как только исчезнет необходимость в том, чтобы он был открыт. +
- +
-==== IX.2.3. Оператор FIELD ==== +
- +
-Как мы уже отмечали,​под каждый контрольный буфер файла (FCB) отводится 265 байтов,​ 256 из которых непосредственно предназначены для временного хранения //​записи//​ файла. +
- +
-Перед началом непосредственной работы с контрольным буфером файла необходимо произвести его разбиение на отдельные //​поля//​ для формирования в них конкретных значений. Делается это при помощи оператора +
-{{anchor:​field}} +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-FIELD [#]n, M1 AS γ1, M2 AS γ2,… , Mk AS γk +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​FIELD''​ ("​field"​ — "​поле"​) — служебное слово;​ +
-  * n — арифметическое выражение,​ целая часть значения которого определяет номер контрольного буфера файла;​ +
-  * M1,M2, …,Mk — целые числа. \\ Учтите,​ что суммарная длина всех объявляемых в операторе ''​FIELD''​ полей не должна превосходить длины записи,​ установленной оператором ''​OPEN''​. Нарушение этого правила приводит к ошибке;​ +
-  * γ1,γ2, …,γk — строковые переменные (простые или с индексами),​ называемые //​буферными//​ переменными;​ +
-  * # — необязательный символ,​ никак не влияющий на выполнение оператора. +
- +
-При выполнении команды ''​FIELD''​ производится задание формата записи. Это выражается в выделении каждому значению буферной переменной γs //​поля//​ из Ms байтов (s=1, 2, …k). +
- +
-Ни одну из буферных переменных оператора ''​FIELD''​ нельзя использовать ни в каких модификациях оператора ''​INPUT''​ и ни одной из них нельзя присваивать значение оператором ''​LET''​. Нарушение любого из этих правил приводит к утрате соответствия,​ установленного оператором ''​FIELD'',​ вследствие чего программа не может больше использовать такую переменную для занесения нужных значений в записи файла или для их извлечения. +
- +
-Разбиение FCB на поля оператором ''​FIELD''​ покажем на рисунке:​ +
-<​code>​ +
-Управляющая информация─┐ ​       M1      M2   ​… ​     Mk +
-    (9 байтов) ​   ┌────▼───┬─────────┬─────┬───┬───────────┐ +
-                  │████████│ ​        ​│ ​    │ … │           │ +
-                  └────────┴────▲────┴──▲──┴───┴─────▲─────┘ +
-                                │       ​│ ​           │ +
-                Значения ───▶ ​  ​γ1 ​     γ2   ​… ​      γk +
-</​code>​ +
- +
-Например,​ оператор ''​FIELD #1,200 AS X$, 12 AS Y$''​ отводит 200 байт для переменной X$ и 12 байтов — для переменной Y$. +
- +
-<WRAP centeralign>​Заметим,​ что этот оператор будет выполнен только в том случае,​ если файл был предварительно открыт.</​WRAP>​ +
- +
-{{anchor:​e0923-01}} __//​Пример 1//__. +
- +
-В качестве примера рассмотрим файл с прямым доступом,​ содержащий информацию о личной библиотеке. Каждая запись +
-содержит следующую информацию:​ +
-  - номер книги (2 байта);​ +
-  - фамилию автора книги (15 байтов);​ +
-  - название книги (30 байтов);​ +
-  - признак наличия книги (1 байт);​ +
-  - информацию о читателе,​ взявшем книгу (22 байта);​ +
-  - дату выдачи книги (10 байтов). +
-Для открытия этого файла и описания структуры записи можно использовать следующие операторы:​ +
-\\ {{.examples:​0923-01.bas|}} \\ [[+tab|wmsxbpge>​0923-01.bas]] +
-<​code>​ +
-10 OPEN "​Библтека"​ AS#1 LEN=80 'В имени - не более 8 символов! +
-20 FIELD #1,2 AS NUMBER$,15 AS AUTHOR$,30 AS BOOK$,1 AS CODE$, 22 AS RADER$,10 AS DATE$ +
-</​code>​ +
- +
-Отметим,​ что разрешается использовать несколько команд ''​FIELD''​ с разными форматами для одного и того же буфера n. Всегда действует то разбиение FCBn на поля, которое предложено последней выполненной командой ''​FIELD''​. +
- +
-{{anchor:​e0923-02}} __//​Пример 2//__. \\ {{.examples:​0923-02.bas|}} \\ [[+tab|wmsxbpge>​0923-02.bas]] +
-<​code>​ +
-10 MAXFILES=3:​OPEN"​Student"​ AS#2 LEN=40 +
-20 FIELD #2,28 AS M1$,12 AS M2$ +
-30 FIELD #2,10 AS M1$,5  AS M2$,24 AS K$ +
-</​code>​ +
-   +
-<WRAP centeralign>​Оператор ''​FIELD''​ должен выполняться перед обращениями к файлу с помощью операторов ''​PUT''​ и ''​GET''​ (см. [[#IX.2.6. Операторы PUT и GET|раздел IX.2.6.]]).</​WRAP>​ +
- +
-Прежде чем обратиться к файлу, Вы должны продумать,​ какие данные будут составлять записи,​ каковы их тип и длина (размер). В результате Вы получите документ,​ часто называемый //​логической структурой файла//​. С ним Вам предстоит работать в течение всего времени "​жизни"​ файла. Поскольку в этом документе указано число байтов,​ отведённое под каждую запись,​ можно заранее установить количество байтов,​ которое потребуется на дискете для конкретного файла, а так как известен и тип применяемых данных,​ то становится очевидным,​ какие придётся вводить переменные. +
-Важно отметить,​ что при известной логической структуре файла его в дальнейшем могут использовать другие программы. +
- +
-Ниже приведена структура записи в файле и дан расчёт размера файла для 24 записей о пловцах. Каждая запись содержит поля для имени пловца,​ клуба, к которому он принадлежит,​ дисциплины,​ в которой он выступает,​ а также поля для его возраста и лучшего показанного результата. +
- +
-//Имя файла//:​ SWIMMER . \\  +
-//Тип файла//:​ прямого доступа. \\  +
-//​Содержимое//:​ 24 записи о пловцах. +
-^  Имя \\ переменной ​ ^  Описание поля ​ ^  Длина поля \\ (байт) ​ ^  Тип данных ​ ^ +
-|  N$  |Имя пловца| ​ 30  |30 символов│ +
-|  T$  |Принадлежность к клубу| ​ 20  |20 символов| +
-|  E$  |Дисциплина| ​ 8  |8 символов| +
-|  A$  |Возраст| ​ 2  |Целое число| +
-|  T  |Лучший результат| ​ 4  |Вещественное число| +
-|  **Итого**:​|| ​ **64** ​ | | +
- +
-Длина и тип каждого поля указаны вместе с переменными,​ которые в Вашей программе будут хранить данные,​ извлечённые из записей. Совершенно необязательно использовать одни и те же переменные во всех программах,​ обращающихся к этому файлу, однако такое единообразие позволит легче проследить ход обработки данных в любой программе. +
- +
-Ещё раз подчеркнём,​ что длина записи в файле с прямым доступом //​постоянна//​. Она определяется при его создании,​ и каждому полю выделяется внутри записи строго определённое место. Возможные значения полей должны умещаться в этом заранее отведённом объёме памяти. Если это не продумано заблаговременно,​ то при выполнении программы чрезмерно "​длинные"​ значения подвергаются усечению,​ а "​короткие"​ дополняются пустующими ячейками памяти. В целях минимизации нежелательного усечения размер каждого поля обычно выбирается достаточно большим,​ чтобы вместить самую большую возможную величину. +
- +
-{{anchor:​lset}} +
-{{anchor:​rset}} +
-==== IX.2.4. Операторы LSET и RSET ==== +
- +
-Напомним Вам, что команда ''​FIELD''​ определяет формат записи файла и набор буферных переменных. Далее буферные переменные не могут использоваться в операторах ''​LET'',​ ''​INPUT'',​ ''​LINE INPUT''​. +
- +
-При формировании в памяти конкретной записи значения буферным переменным из ''​FIELD''​ присваиваются операторами:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-LSET γ=β +
-</​code>​ +
-<​code>​ +
-RSET γ=β  +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​LSET''​ ("Left SET" — "​поместить слева"​),​ +
-  * ''​RSET''​ ("​Right SET" — "​поместить справа"​) — служебные слова;​ +
-  * γ — имя буферной переменной;​ +
-  * β — строковое выражение (β≠γ). +
- +
-Пусть буферной переменной γ отведено в буфере поле размером m байтов. Выполнение оператора ''​LSET''​ начинается с вычисления значения выражения β. +
-Далее, если это необходимо,​ его длина приводится к величине m за счёт отбрасывания лишних //​правых//​ символов или добавления справа недостающего количества пробелов. Полученное значение присваивается буферной переменной γ и размещается в соответствующем поле буфера файла. +
- +
-Оператор ''​RSET''​ выполняется почти так же, как и оператор ''​LSET''​. Разница состоит в том, что при выравнивании значения β до длины m возможные недостающие пробелы добавляются к нему не справа,​ а //​слева//​. Неиспользованные +
-байты заполняются пробелами. Таким образом,​ операторы ''​LSET''​ и ''​RSET''​ гарантируют,​ что длина значения переменной будет приведена в соответствие с длиной,​ указанной в операторе ''​FIELD''​. +
- +
-{{anchor:​e0924-01}} __//​Пример 1//__. \\ {{.examples:​0924-01.bas|}} \\ [[+tab|wmsxbpge>​0924-01.bas]] +
-<​code>​ +
-10 OPEN "​EF"​ AS#1 LEN=9 +
-20 FIELD #1,5 AS M$,14 AS L$ +
-30 INPUT R$:LSET M$=R$ +
-40 INPUT R$:RSET L$=R$ +
-50 PRINT M$:PRINT L$ +
-run +
-? КРАТЕР ​                  M$ +
-? НЕБОСВОД ​      ​┌───┬───┬───┬───┬───┬ +
-КРАТЕ ​           │ K │ Р │ А │ Т │ Е │ +
-      НЕБОСВОД ​  ​└───┴───┴───┴───┴───┴ +
-Ok                      5 байтов +
-</​code>​ +
- +
-{{anchor:​e0924-02}} __//​Пример 2//__. \\ {{.examples:​0924-02.bas|}} \\ [[+tab|wmsxbpge>​0924-02.bas]] +
-Приведём фрагмент программы,​ в котором формируется запись файла, содержащего информацию о личной библиотеке. +
-В буфер заносится информация о романе Л.Н.Толстого "​Война и мир"​. Структура записи была рассмотрена ранее. +
-<​code>​ +
-10 OPEN "​Библтека"​ AS#1 LEN=80 +
-20 FIELD #1,2 AS NUMBER$,15 AS AUTHOR$,30 AS BOOK$,1 AS CODE$, 22 AS RADER$,10 AS DATE$ +
-30 LSET NUMBER$=10 ​                '​Шифр книги +
-40 LSET AUTHOR$="​Л.Н.Толстой"​ +
-50 LSET BOOK$="​Война и мир"​ +
-60 LSET CODE$="​X" ​                 'X - книга хранится +
-70 LSET READER$="​ " ​               '​Читатель,​ разумеется,​ отсутствует +
-80 LSET DATE$="​10.5.1988"​ +
-</​code>​ +
- +
-Команды ''​LSET''​ и ''​RSET''​ можно использовать не только при работе с файлами. +
- +
-{{anchor:​e0924-03}} __//​Пример 3//__. \\ {{.examples:​0924-03.bas|}} \\ [[+tab|wmsxbpge>​0924-03.bas]] +
-<​code>​ +
-10 L$=SPACE$(20):​Z$="​Волк"​ +
-20 RSET L$=Z$:PRINT L$ +
-</​code>​ +
- +
-==== IX.2.5. Функции MKI$(), MKS$(),​MKD$(),​ CVI(), CVS(), CVD() ==== +
- +
-Вам, конечно,​ известно,​ что буферные переменные являются строковыми. Пусть γ — буферная переменная и ей командой ''​FIELD''​ в FCB отведено поле длиной m байтов. Если требуется "​упаковать"​ в γ числовое значение,​ то пользуются функциями:​ +
-  - <​WRAP>​ {{anchor:​mki}} +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​MKI$(L)</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​MKI''​ ("MaKe Integer"​ — "​преобразовать целое значение"​) — служебное слово;​ +
-  * L — арифметическое выражение целого типа; +
-  * m=2; +
-</​WRAP>​ +
-  - <​WRAP>​{{anchor:​mks}} +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​MKS$(L)</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​MKS''​ ("MaKe Single"​ — "​преобразовать значение одинарной точности"​) — служебное слово;​ +
-  * L — арифметическое выражение одинарной точности;​ +
-  * m=4; +
-</​WRAP>​ +
-  - <​WRAP>​{{anchor:​mkd}} +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​MKD$(L)</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​MKD''​ ("MaKe Double"​ — "​преобразовать значение двойной точности"​) — служебное слово;​ +
-  * L — арифметическое выражение двойной точности;​ +
-  * m=8. +
-</​WRAP>​ +
-Каждая из этих функций преобразует значение арифметического выражения L к строковому типу. После этого операторами ''​[[#​lset|LSET]]''​ или ''​[[#​rset|RSET]]''​ эти значения можно разместить в γ и соответствующем поле буфера. +
- +
-Обращаем Ваше внимание на тот факт, что функции ''​MKI$()'',​ ''​MKS$()''​ и ''​MKD$()''​ не переводят числовые величины в эквивалентные им знаки кода ASCII, как это делается при использовании других функций. Они просто "​упаковывают"​ соответствующие значения в два,​четыре или восемь знаков по той же схеме, которая реализуется в компьютере для представления числовых величин в оперативной памяти. Именно поэтому с помощью оператора ''​PRINT'' ​ невозможно выдать на печать или экран дисплея результаты работы функций ''​MKI$()'',​ +
-''​MKS$()''​ и ''​MKD$()''​ ! +
- +
-__//​Пример 1//__. +
- +
-  - функция ''​MKI$(17217)''​ возвращает строку "​AC"​. Рассмотрим,​ как это получается:​ <​code>​ +
-17217=&​B0100001101000001=&​H4341=&​H43·256+&​H41=67·256+65 +
-        └──────┘└──────┘ ​                     ▲      ▲ +
-            C       ​A ​                        ​│ ​     └─ Код символа "​A"​ +
-                                              └──────── Код символа "​C"​ +
-</​code>​ +
-  - ''​MKS$(4.14141)''​ возвращает строку %% "​AAAA"​ %% +
- +
-{{anchor:​e0925-02}} __//​Пример 2//__. \\ {{.examples:​0925-02.bas|}} \\ [[+tab|wmsxbpge>​0925-02.bas]] +
-<​code>​ +
-1 A$=MKI$(&​HE276):​PRINT HEX$(ASC(MID$(A$,​1,​1)));"​ ";​HEX$(ASC(MID$(A$,​2,​1))) +
-76 E2 +
-Ok +
-</​code>​ +
- +
-{{anchor:​e0925-03}} __//​Пример 3//__. \\ {{.examples:​0925-03.bas|}} \\ [[+tab|wmsxbpge>​0925-03.bas]] +
-<​code>​ +
-10 MAXFILES=5:​OPEN "​LU"​ AS#4 +
-20 FIELD #4, 2 AS A$, 4 AS B$, 8 AS E$ +
-30 INPUT X%:LSET A$=MKI$(X%) +
-40 INPUT Y!:LSET B$=MKS$(Y!) +
-50 INPUT Z#:LSET E$=MKD$(Z#​) +
-60 PRINT A$;" ";​B$;"​ ";E$ +
-70 RSET A$=MKI$(X%):​RSET B$=MKS$(Y!):​RSET E$=MKD$(Z#​) +
-80 PRINT A$;" ";​B$;"​ ";E$ +
-run +
-? 1096 +
-? 1.535 +
-? -3.4 +
-H A5 a4 +
-H A5 a4 +
-Ok +
-</​code>​ +
-Функции ''​MKI$()'',​ ''​MKS()''​ и ''​MKD()''​ выполняют обратное преобразование по отношению к функциям ''​CVI()'',​ ''​CVS()''​ и ''​CVD()'',​ к рассмотрению которых мы сейчас приступаем. +
- +
-Пусть в буфер с дискеты считана запись и в некотором её поле,​определённом по команде ''​FIELD''​ элементом +
-<​code>​ +
-m AS γ +
-</​code>​ +
-"​упаковано"​ числовое значение. "​Распаковка"​ его или, выборка из γ этого значения,​ реализуется одной из следующих функций:​ +
-  - <​WRAP>​{{anchor:​cvi}} +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​CVI(γ)</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​CVI''​ ("​ConVert to Integer"​ — "​преобразовать к целому"​) — служебное слово;​ +
-  * γ — имя буферной переменной;​ +
-  * m=2; +
-</​WRAP>​ +
-  - <​WRAP>​{{anchor:​cvs}} +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​CVS(γ)</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​CVS''​ ("​ConVert to Single"​ — "​преобразовать к значению одинарной точности"​) — служебное слово;​ +
-  * γ — имя буферной переменной;​ +
-  * m=4; +
-</​WRAP>​ +
-  - <​WRAP>​{{anchor:​cvd}} +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​CVD(γ)</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​CVD''​ ("​ConVert to Double"​ — "​преобразовать к значению двойной точности"​) — служебное слово;​ +
-  * γ — имя буферной переменной;​ +
-  * m=8. +
-</​WRAP>​ +
-Эти функции преобразуют строки символов в числа. Аргумент состоит из 2, 4 или 8 байтов и преобразуется в целое число, либо число с одинарной или двойной точностью,​ в зависимости от вида используемой функции (''​CVI'',​ ''​CVS''​ или ''​CVD''​). +
- +
- +
-//​Пример 4//.  +
-  - <​WRAP>​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-print CVI("​AC"​) +
- ​17217 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-так как +
-<​code>​ +
-print MKI$(17217) +
-AC +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-  - <​WRAP>​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-print CVS("​GWYF"​) +
- ​5759460 +
-Ok +
-</​code>​ +
- +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-так как +
-<​code>​ +
-print MKS$(5759460) +
-GWYF +
-Ok +
-</​code>​ +
-</​WRAP>​ +
- +
-Посмотрите на схему… +
-<​code>​ +
-       "​G" ​        "​W" ​       "​Y" ​       "​F"​ +
-    0100 0111   0101 0111  0101 1001  0100 0110 +
-    ▲───▲──── ​   5    7     ​5 ​   9     ​4 ​   6 +
-    │   │ +
-    │ Порядок числа = &​B1000111-&​B1000000 = &B111 = 7 +
-Знак числа +
-</​code>​ +
-Сравните эти результаты с представлением чисел в памяти компьютера (см. далее главу 10). +
- +
-{{anchor:​e0925-05}} __//​Пример 5//__. \\ {{.examples:​0925-05.bas|}} \\ [[+tab|wmsxbpge>​0925-05.bas]] +
-<​code>​ +
-10 OPEN "​SL"​ AS#1 LEN=8:FIELD #1,8 AS R$ +
-20 INPUT X:RSET R$=MKD$(X) +
-40 PRINT R$,​CVD(R$) +
-run +
-? 123 +
-C0          123 +
-Ok +
-</​code>​ +
- +
-==== IX.2.6. Операторы PUT и GET ==== +
-FIXME +
- +
-{{anchor:​put}} +
-Для пересылки ("​сброса"​) сформированной в оперативной памяти записи на дискету используется оператор +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-PUT [#]n[,P] +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-где: +
-  * ''​PUT''​ ("​записать",​ "​разместить"​) — служебное слово;​ +
-  * n, P — арифметические выражения,​ целые части значений которых задают соответственно номер контрольного буфера файла и номер записи. +
- +
-До выполнения оператора ''​PUT''​ в оперативной памяти:​ +
-  * оператором ''​MAXFILES=''​ должен быть объявлен контрольный буфер файла FCBn ; +
-  * открыт некоторый файл В, связанный с FCBn (оператором ''​OPEN''​);​ +
-  * задан формат его записей (оператором ''​FIELD''​) и, наконец,​ +
-  * в FCBn создана сама запись (операторами ''​LSET'',​ ''​RSET''​). +
-После всей этой процедуры оператором ''​PUT''​ содержимое FCBn будет выведено под номером P на дискету,​ или, как говорят,​ //​сформирована//​ новая или //​обновлена//​ старая запись Р файла В. +
- +
-При открытии файла значение Р равно 0. //​Текущим//​ значением Р считается номер той записи,​ с которой работал последний выполненный оператор ''​PUT''​ или ''​GET''​. Далее, если в операторе ''​PUT''​ параметр Р не указан,​ то берётся его текущее значение,​ увеличенное на 1. +
- +
-Например,​ в операторе ''​PUT #​1,​3''​ второе число (3) определяет номер записи в файле. Если этот номер будет +
-пропущен,​ то будет использовано число, на единицу большее,​чем в последнем выполненном операторе ''​PUT''​ или ''​GET''​. +
- +
-Номер записи может находиться в диапазоне от 1 до 4294967295, в чем Вы можете убедиться самостоятельно. +
- +
-{{anchor:​e0926-01}} __//​Пример 1//__. \\ {{.examples:​0926-01.bas|}} \\ [[+tab|wmsxbpge>​0926-01.bas]] +
-<​code>​ +
-10 REM формирование файла +
-20 MAXFILES=2:​OPEN"​массив"​ AS#2 LEN=8:FIELD #2,8 AS M +
-50 FOR I=1 TO 30 +
-60    INPUT"​Введите число";​А:​LSET M=MKD$(A):​PUT #2 +
-90 NEXT +
-100 CLOSE #2 +
-</​code>​ +
- +
-{{anchor:​e0926-02}} __//​Пример 2//__. \\ {{.examples:​0926-02.bas|}} \\ [[+tab|wmsxbpge>​0926-02.bas]] +
-<​code>​ +
-10 '​Объявление FCB0, FCB1, FCB2 и FCB3 +
-20 '​Открытие файла "​рыба"​ с буфером #2 +
-30 MAXFILES=3:​OPEN "​Рыба"​ AS#2 LEN=13 +
-40 '​Определение формата записи +
-50 FIELD #2,8 AS L$, 5 AS M$ +
-60 '​Формирование первых 10 записей +
-70 FOR K=1 TO 10 +
-80    INPUT"​X$-8";​X$:​INPUT"​Y$-5";​Y$ +
-90    LSET L$=X$:RSET M$=Y$:PUT #2,K +
-99 NEXT:END +
-</​code>​ +
-Пусть открыт некоторый файл данных,​ связанный с буфером FCBn. Полезную информацию о файле можно извлечь с помощью функций ''​[[#​LOF]]''​ и ''​[[#​LOC]]''​. +
- +
-{{anchor:​get}} +
-Для считывания записей файла с дискеты в оперативную память используется оператор +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-GET [#]n[,P] +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​GET''​ ("to get" — "​получать"​) — служебное слово;​ +
-  * n, P — арифметические выражения,​ целые части значений которых задают соответственно номер контрольного буфера файла и номер записи. +
-До выполнения оператора ''​GET''​ необходимо:​ +
-  * объявить контрольный буфер файла FCBn (оператором ''​MAXFILES=''​);​ +
-  * открыть некоторый файл данных В,​связанный с FCBn (оператором ''​OPEN''​);​ +
-  * задать формат его записей (оператором ''​FIELD''​). +
-После всей этой процедуры по оператору ''​GET''​ с диска в буфер # n будет считана запись с номером Р. Фактически будут сформированы значения всех строковых переменных буфера (числовые значения буферных переменных надо "​распаковать"​ с помощью функций ''​CVI'',​ ''​CVS''​ и ''​CVD''​). +
- +
-Например,​ оператор ''​GET #​1,​3''​ выполняет передачу записи с номером 3 из файла #1 в буфер полей. +
- +
-Если в записи оператора параметр Р отсутствует,​ то берётся текущее значение этого параметра,​ увеличенное на единицу (как и в операторе ''​PUT''​). +
- +
-{{anchor:​e0926-03}} __//​Пример 3//__. \\ {{.examples:​0926-03.bas|}} \\ [[+tab|wmsxbpge>​0926-03.bas]] +
-<​code>​ +
-10 REM Считывание из файла "​Массив"​ +
-20 MAXFILES=2:​OPEN"​Массив"​ AS#2 LEN=8:FIELD 2,8 AS M +
-50 FOR I=30 TO 1 STEP-1 +
-60     GET 2,I:PRINT CVD(M); +
-80 NEXT +
-</​code>​ +
- +
-{{anchor:​e0926-04}} __//​Пример 4//__. \\ {{.examples:​0926-04.bas|}} \\ [[+tab|wmsxbpge>​0926-04.bas]] +
-<​code>​ +
-1 OPEN"​числа"​ AS#1 LEN=10 +
-2 FIELD #1,2 AS A$(1),2 AS A$(2),2 AS A$(3),2 AS A$(4),2 AS A$(5) +
-3 FOR I=1 TO 5:LSET A$(I)=MKI$(I):​NEXT I +
-8 PUT #1,1:CLOSE #1:END +
-10 OPEN"​числа"​ AS#1 +
-11 FIELD #1,2 AS B$(1),2 AS B$(2),2 AS B$(3),2 AS B$(4),2 AS B$(5) +
-12 GET #1,1 +
-13 FOR I=1 TO 5:​A(I)=CVI(B$(I)):​NEXT I +
-18 P=1:FOR T=1 TO 5:​P=P+A(T):​NEXT T +
-19 PRINT P:CLOSE #1:END +
-</​code>​ +
- +
-{{anchor:​e0926-05}} __//​Пример 5//__. \\ {{.examples:​0926-05.bas|}} \\ [[+tab|wmsxbpge>​0926-05.bas]] +
-<​code>​ +
-10 CLOSE:​OPEN"​числа"​ AS#1 LEN=25 +
-30 FIELD #1,5 AS A$(1),5 AS A$(2),5 AS A$(3),5 AS A$(4), 5 AS A$(5) +
-40 FOR T=1 TO 5 +
-50     ​LINEINPUT"​Еще слово:";​J$(T):​LSET A$(T)=J$(T) +
-60 NEXT T +
-70 PUT#​1,​1:​CLEAR '​Чистка оперативной памяти +
-90 OPEN"​числа"​ AS#1 +
-100 FIELD #1,5 AS B$(1),5 AS B$(2),5 AS B$(3),5 AS B$(4), 5 AS B$(5) +
-110 GET#​1,​1:​U$=""​ +
-120 FOR T=1 TO 5:​U$=U$+B$(T):​NEXT T +
-150 PRINT"​Сумма:";​U$ +
-</​code>​ +
- +
-{{anchor:​e0926-06}} __//​Пример 6//__. \\ {{.examples:​0926-06.bas|}} \\ [[+tab|wmsxbpge>​0926-06.bas]] +
-<​code>​ +
-10 CLOSE:​OPEN"​числа"​ AS#1 LEN=25 +
-20 FIELD #1,5 AS A$(1),4 AS A$(2),5 AS A$(3),4 AS A$(4), 5 AS A$(5) +
-30 FOR T=1 TO 5 STEP 2 +
-40     ​LINEINPUT"​Еще слово:";​J$(T) +
-50     LSET A$(T)=J$(T):​NEXT +
-60 FOR T=2 TO 4 STEP 2 +
-70     ​INPUT"​Еще число";​J(T) +
-80     LSET A$(T)=MKS$(J(T)):​NEXT +
-90 PUT #​1,​1:​CLEAR ​ '​Чистка оперативной памяти +
-110 OPEN"​числа"​ AS#1 +
-120 FIELD #1,5 AS B$(1),4 AS B$(2),5 AS B$(3),4 AS B$(4), 5 AS B$(5) +
-130 GET #​1,​1:​U$=B$(1) +
-140 FOR T=2 TO 4 STEP 2 +
-150     ​U$=U$+STR$(CVS(B$(T)))+B$(T+1):​NEXT +
-160 PRINT"​Сумма:";​U$ +
-</​code>​ +
- +
-Отметим ключевой момент при работе с файлами //​прямого//​ доступа:​ отслеживание "​невидимых"​ указателей. Их два: для дискеты и для буфера. +
- +
-Первый указатель содержит ссылку на текущую запись и задаётся номером в операторах ''​PUT''​ или ''​GET''​. +
- +
-Буферный указатель ссылается на элемент данных — переменную,​ которая в этот момент пишется или читается. Он задаётся длиной полей в операторе ''​FIELD''​. +
- +
-Ниже приведены //две схемы//,​ дающие наглядное представление о последовательности операций,​ которые должны быть выполнены при перемещениях //​записей//​ файлов прямого доступа из оперативной памяти на дискету и в обратном направлении. +
-  - <​WRAP>​Общая схема формирования //​новых//​ записей уже существующего или вновь создаваемого файла F. +
-  * А. В оперативной памяти резервируется буфер (оператором ''​MAXFILES=''​) +
-  * B. //​Открывается//​ файл F (оператором ''​OPEN''​) +
-  * C. Производится распределение полей буфера файла под значения переменных (оператором ''​FIELD''​) +
-  * D. В буфере формируется запись (при помощи операторов ''​SET'',​ ''​RSET''​ и функций ''​MKI$()'',​ ''​MKS$()'',​ ''​MKD$()''​ +
-  * E. Производится "​сброс"​ записи из буфера на дискету с присваиванием ей некоторого номера (оператором ''​PUT''​) +
-  * F. Файл F //​закрывается//​ (оператором ''​CLOSE''​) +
- +
-{{anchor:​e0926-07}} \\ __//​Пример 7//__. Запись слова в файл прямого доступа. \\ {{.examples:​0926-07.bas|}} \\ [[+tab|wmsxbpge>​0926-07.bas]] +
-<​code>​ +
-10 MAXFILES=2:​OPEN "​EASY"​ AS#2:FIELD #2,18 AS N$,110 AS D$ +
-20 LSET N$="​Психокомпьютерапия":​LSET D$=" ":PUT #2,1:CLOSE #2 +
-</​code>​ +
-</​WRAP>​ +
-  - <​WRAP>​Общая схема //​считывания//​ записей из уже существующего файла. +
-  * А. В оперативной памяти резервируется буфер (оператором ''​MAXFILES=''​)│ +
-  * B. //​Открывается//​ файл F (оператором ''​OPEN''​) +
-  * C. Производится распределение полей буфера файла под значения переменных (оператором ''​FIELD''​) +
-  * D. Производится считывание с диска в буфер оперативной памяти записи с конкретным номером (оператором ''​GET''​) +
-  * E. По записи из буфера в соответствии с распределением его поля формируются значения требуемых переменных (при помощи функций ''​CVI()'',​ ''​CVS()'',​ ''​CVD()''​). После перенесения записи в буфер Вы можете манипулировать данными,​ полученными из файла, так же, как любыми другими переменными. <WRAP centeralign>​Пункты D и E повторяются столько раз, сколько это требуется</​WRAP>​ +
-  * F. Файл F //​закрывается//​ (оператором ''​CLOSE''​) +
-</​WRAP>​ +
- +
-{{anchor:​e0926-08}} __//​Пример 8//__. Чтение слова из файла прямого доступа. \\ {{.examples:​0926-08.bas|}} \\ [[+tab|wmsxbpge>​0926-08.bas]] +
-<​code>​ +
-10 MAXFILES=2:​OPEN "​EASY"​ AS#2:FIELD #2,18 AS N$,110 AS D$ +
-20 GET #2,1:PRINT N$:CLOSE #2 +
-run +
-Психокомпьютерапия +
-Ok +
-</​code>​ +
- +
-В заключении этого пункта приведём примеры,​ иллюстрирующие действие изученных Вами операторов и функций при работе с дисковыми файлами данных прямого доступа. +
- +
-{{anchor:​e0926-09}} __//​Пример 9//__. \\ {{.examples:​0926-01.bas|}} \\ [[+tab|wmsxbpge>​0926-09.bas]] +
-<​code>​ +
-5 CLS +
-10 OPEN "​ЭКЗАМЕН"​ AS#1 LEN=45:​FIELD#​1,​5 AS G$,25 AS F$,1 AS O$ +
-25 INPUT "​Введите количество студентов";​N +
-30 FOR I=1 TO N +
-40    INPUT "​Группа";​GG$:​INPUT "​Ф.И.О";​FF$:​INPUT"​Оценка";​OO$ +
-50    LSET G$=GG$:LSET F$=FF$:LSET O$=OO$:PUT #1,I +
-65 NEXT:CLS +
-66 FOR I=1 TO N +
-70    GET #1,I:IF O$="​5"​ OR O$="​4"​ THEN PRINT G$,F$;O$ +
-80 NEXT +
-90 CLOSE #1 +
-</​code>​ +
- +
-{{anchor:​e0926-10}} __//​Пример 10//__. Дана таблица:​ +
-^  Ф.И. ученика ​ ^  Тема ​ ^  Балл ​ ^ +
-|  Фомина Н.  |  Графика ​ |  5  | +
-|:::|  Массивы ​ |  5  | +
-|  Бобкова Н.  |  Графика ​ |  4  | +
-|:::|  Массивы ​ |  3  | +
-||  …  || +
-|  Герасимова Е.  |  Графика ​ |  5  | +
-|:::|  Массивы ​ |  3  | +
-Заполнить два файла:​ +
-  - список учеников,​ у которых средний балл по двум темам ≥ 4 ; +
-  - список учеников,​ у которых хотя бы по одной теме балл 4 или 5. +
-{{.examples:​0926-10.bas|}} \\ [[+tab|wmsxbpge>​0926-10.bas]] +
-<​code>​ +
-10 MAXFILES=3 +
-20 OPEN "​экзамен"​AS#​1 LEN=39 +
-30 FIELD #1, 15 AS I$,  10 AS T1$,  2 AS O1$,  10 AS T2$,  2 AS O2$ +
-31' ​               ▲          ▲          ▲           ​▲ ​         ▲ +
-32' ​               │          │          │           ​│ ​         │ +
-33' ​        ​Фамилия,​имя ​   Первая ​    ​Балл по     ​Вторая ​    ​Балл по +
-34' ​                        ​тема ​   первой теме ​   тема ​   второй теме +
-40 OPEN "​Фамилия"​AS#​2 LEN=15 +
-50 FIELD #2,15 AS F$     '​Фамилия ученика,​ у которого средний балл ​ по '​двум темам ≥ 4 +
-60 OPEN "​особенное"​AS#​3 LEN=15 +
-70 FIELD #3,15 AS F1$    '​Фамилия ученика,​ у которого хотя бы по одной '​теме балл 4 или 5 +
-75 INPUT "​Введите количество учащихся";​N +
-80 FOR I=1 TO N +
-90     INPUT "​Ф.И.";​D$:​LSET I$=D$:INPUT "​Тема1";​D$:​LSET T1$=D$:​INPUT"​Балл";​D%:​LSET O1$=MKI$(D%):​INPUT "​Тема2";​D$:​LSET T2$=D$:​INPUT "​Балл";​D%:​LSET O2$=MKI$(D%):​PUT#​1,​I +
-110 NEXT:​A=0 ​      '​A - количество учеников,​ у которых средний балл по '​двум темам ≥ 4 +
-120 FOR K=1 TO N:​GET#​1,​K ​                         '​Заполнение файла #2 +
-125     ​L=(CVI(O1$)+CVI(O2$))/​2 +
-130     IF L>=4 THEN LSET F$=I$:​A=A+1:​PUT #2,A +
-140 NEXT K +
-146 PRINT"​Ф.И. хорошистов и отличников:"​ +
-150 FOR I=1 TO A:GET #2,I:PRINT F$:NEXT I         '​Вывод на экран +
-170 B=0            'B - количество учеников,​у которых хотя бы по одной '​теме балл 4 или 5 +
-175 FOR K=1 TO N                                  '​Заполнение файла #3 +
-177     GET #1,K +
-180     IF CVI(O1$)=4 OR CVI(O1$)=5 OR CVI(O2$)=4 OR CVI(O2$)=5 THEN LSET F1$=I$:​B=B+1:​PUT #3,B +
-190 NEXT K +
-195 PRINT"​Ф.И. успевающих"​ +
-200 FOR I=1 TO B:​GET#​3,​I:​PRINT F1$:NEXT I:END     '​Вывод на экран +
-</​code>​ +
- +
-{{anchor:​e0926-11}} __//​Пример 11//__. \\ {{.examples:​0926-11.bas|}} \\ [[+tab|wmsxbpge>​0926-11.bas]] +
-<​code>​ +
-10 MAXFILES=3:​OPEN"​A3"​ AS#2 LEN=2:FIELD #2,2 AS K$ +
-20 POKE VARPTR(#​2)+9,​66:​POKE VARPTR(#​2)+10,​65 ​ '​Вместо LSET K$="​ba"​ +
-30 PUT #​2,​2:​CLOSE#​2 +
-40 OPEN"​a3"​AS#​2 LEN=2:FIELD #2,2 AS K$:GET #2,2:CLOSE #2 +
-run +
-ba +
-Ok +
-</​code>​ +
- +
-===== IX.3. Файлы данных последовательного доступа ===== +
- +
-При использовании дискеты достаточно указать имя файла, чтобы компьютер начал поиск с использованием каталога. Все участки дискеты в равной степени доступны для записи и чтения,​ т.е. для обращения к любому участку требуется примерно одинаковое время. Напомним Вам, что <WRAP centeralign>​файл,​ в котором информация может быть найдена без полного просмотра носителя,​ мы назвали файлом с //​прямым//​ доступом.</​WRAP>​ +
- +
-<WRAP centeralign>​Файл будем называть файлом с //​последовательным доступом//,​ если компьютер должен "​просматривать"​ его с самого начала до момента нахождения нужной части.</​WRAP>​ +
- +
-Поиск файла на кассетной ленте называется //​последовательным//,​ потому что компьютер ищет требуемый файл, последовательно перематывая магнитную ленту. +
- +
-Любой файл можно организовать так, чтобы можно было использовать либо последовательный,​ либо прямой доступ,​ но не оба способа одновременно. Каждый способ имеет свои "​за"​ и "​против"​. Последовательный способ намного проще для программирования и при его реализации требуется меньше дисковой памяти,​ но может понадобиться больше времени для поиска информации,​ находящейся "в конце"​ длинного файла. Кроме того, обновление существующих записей в файлах с последовательным доступом трудноосуществимо,​ а иногда и просто невозможно. +
- +
-Файлы с прямым доступом требуют более сложного программирования и занимают обычно больше места на дискете,​ но очень легко поддаются обновлению,​ и поиск нужной информации осуществляется с одинаковой скоростью. +
- +
-<WRAP centeralign>​Если при каждом обращении к файлу Вы собираетесь использовать почти все данные,​ а менять их содержимое часто не предполагается,​ то выбирайте метод //​последовательного//​ доступа. Его применение будет и более оптимальным и облегчит Вам программирование.</​WRAP>​ +
- +
-Файлы данных последовательного доступа состоят из отдельных групп значений,​ называемых //​логическими//​ строками (или просто //​строками//​). +
- +
-Логические строки не имеют номеров и их можно считывать с дискеты или магнитной ленты в оперативную память или записывать из памяти на дискету или магнитную ленту лишь последовательно друг за другом,​ причём запись производится от начала или конца файла, а чтение — только от его начала. +
- +
-<WRAP centeralign>​Каждая логическая строка имеет специальную //​концевую//​ метку, а весь файл имеет ещё и метку EOF ("End Of File" — "​конец файла"​).</​WRAP>​ +
- +
-Кроме того, любой конкретный файл открывается или только для чтения,​ или только для записи,​ но не для одновременного выполнения этих операций. +
- +
-Для работы с файлами данных //​последовательного//​ доступа в [[msx:​disk_basic]] предусмотрен ряд операторов и функций. +
- +
-==== IX.3.1. Оператор MAXFILES=, OPEN и CLOSE ==== +
- +
-Перемещение логических строк последовательных файлов из оперативной памяти на дискету и в обратном направлении производится через //​контрольные буферы файлов//​. Последние объявляются оператором ''​MAXFILES=''​. Максимальное количество файлов,​ которые могут быть открыты одновременно,​ устанавливается оператором +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-MAXFILES=A +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​MAX'',​ ''​FILES''​ — служебные слова;​ +
-  * A — арифметическое выражение,​ целая часть значения которого принадлежит отрезку [0,15]. +
-При включении компьютера значение параметра A равно 1. Таким образом,​ если Вы хотите открыть //​только один// файл, то использование оператора ''​MAXFILES''​ необязательно. +
- +
-<WRAP centeralign>​Файл #0 всегда открыт. [[msx:​disk_basic]] использует контрольный буфер этого файла для "​своих нужд"​ (он используется при выполнении операторов ''​LOAD'',​ ''​SAVE'',​ ''​KILL'',​ ''​RUN'',​ ''​MERGE''​).</​WRAP>​ +
- +
-При работе с последовательными файлами буфера используются самым простым способом:​ пересылаемые в файл данные накапливаются в буфере файла, а по заполнении буфера его содержимое сразу целиком переписывается в дисковый файл;​при этом буфер файла очищается для следующей порции выходных данных. При чтении файла соответствующие данные поступают из того же самого буфера,​ а не считываются непосредственно с поверхности дискеты. Как только все необходимые данные считаны из буфера,​ средства [[msx:​basic:​]] обеспечивают повторное его заполнение информацией из дискового файла. +
- +
-Учтите,​что при использовании оператора ''​MAXFILES=''​ автоматически выполняется оператор ''​CLEAR'',​ но если Вы используете в программе оба оператора,​ то располагайте оператор ''​MAXFILES=''​ вслед за оператором ''​CLEAR''​. +
- +
-Вам, конечно же, ясно, что перед использованием файла Вы должны объявить его //​открытым//​. Открытие файла осуществляется оператором ''​OPEN'',​ в котором задаётся:​ +
-  * имя устройства (''​A:'',​ ''​B:'',​ ''​MEM:'',​ ''​CAS:'',​ ''​CRT:'',​ ''​GRP:'',​ ''​LPT:'',​ ''​COM:''​);​ +
-  * имя файла;​ +
-  * направление потока данных;​ +
-  * номер, присвоенный файлу для передачи данных. +
-Синтаксис оператора ''​OPEN'':​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-           ⎧ INPUT +
-OPEN B FOR ⎨ OUTPUT ​ AS[#]n +
-           ⎩ APPEND +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​OPEN''​("​открыть"​),​ FOR("​для"​),​ ''​INPUT''​("​ввод"​),​ ''​OUTPUT''​("​вывод"​),​ ''​APPEND''​("​присоединение"​) — служебные слова;​ +
-  * В — строковое выражение,​ значение которого задаёт имя устройства и имя файла. +
-Сейчас мы познакомим Вас с именами //​устройств//:​ +
-  * устройство ''​CRT:''​ отвечает за вывод информации на //​текстовый//​ экран ("​CaRet"​ — "​символ"​);​ +
-  * устройство ''​GRP:''​ отвечает за вывод информации на экран в //​графических//​ режимах ("​GRaPhics"​ — "​графика"​);​ +
-  * устройство ''​LPT:''​ отвечает за вывод информации на //​принтер//​ ("Line PrinT" — "​печать строки"​);​ +
-  * устройство ''​COM:''​ (только для компьютеров [[msx:​msx_1]]) отвечает за движение информации по //​локальной//​ сети ("​COMmunication"​ — "​передача данных"​);​ +
-  * устройство ''​MEM:''​ (только для [[msx:​msx_2]]) — это не что иное, как RAM диск ("​MEMory"​ — "​память"​);​ +
-  * устройство ''​CAS:''​ является накопителем на магнитной ленте (//​магнитофоном//​) ("​CASsette type" — "​кассетная лента"​);​ +
-  * n — арифметическое выражение,​ целая часть значения которого принадлежит:​ +
-    * отрезку [0,6] для файлов на дискете,​ +
-    * отрезку [0,15] для файлов на других устройствах,​ и определяет номер контрольного буфера файла;​ +
-  * # — необязательный символ. +
- +
-При выполнении оператора ''​OPEN''​ файлу В "​назначается"​ для работы контрольный буфер файла с номером n. +
- +
-Параметры ''​INPUT'',​ OUTPUT и APPEND указывают направление последующего движения информации относительно компьютера. +
- +
-Оператор ''​OPEN''​ с параметром ''​INPUT''​ открывает файл //для ввода//​ строк с дискеты в буфер. Чтение будет организовано от начала файла. +
- +
-Оператор ''​OPEN''​ с параметром ''​OUTPUT''​ открывает файл //для вывода//​ строк с буфера на дискету. Запись будет осуществляться от начала файла. Оператор ''​OPEN''​ с параметром ''​APPEND''​ открывает файл для вывода строк с буфера на дискету,​но запись будет производиться с //​конца//​ файла. +
- +
-Будьте осторожны:​ параметр ''​APPEND''​ не может использоваться при открытии файлов на устройствах ''​CAS:'',​ ''​CRT:'',​ ''​GRP:'',​ ''​LPT:''​ и ''​COM:''​ ! +
- +
-Параметр ''​INPUT''​ не может использоваться при открытии файлов на устройствах ''​CRT:'',​ ''​GRP:''​ и ''​LPT:''​ +
- +
-<​code>​ +
-┌───────────────────────────┐ ​         ┌───────────────────────┐ +
-│       ​Контрольный ​        ​◀───INPUT──│ ​                      │ +
-│           ​буфер ​          ​│──OUTPUT──▶ ​       Дискета ​       │ +
-│           ​файла ​          ​│──APPEND──▶ ​                      │ +
-└───────────────────────────┘ ​         └───────────────────────┘ +
-</​code>​ +
- +
-Оператор ''​OPEN''​ с параметром ''​FOR OUTPUT''​ создаёт новый дисковый файл с заданным именем. Если файл с таким именем уже есть,​то он автоматически уничтожается и создаётся новый файл с тем же именем. +
- +
-Оператор ''​OPEN…FOR APPEND''​ обеспечивает поиск названного файла среди уже существующих,​ с тем чтобы добавить новые записи в его конец, но если требуемого файла найти не удалось,​ то автоматически создаётся новый файл +
-с заданным именем. +
- +
-Модификация оператора с параметром ''​FOR INPUT''​ реализует поиск данных с конкретным именем,​ отсутствие которого означает ошибку. +
- +
-__//​Примеры//​__:​ +
-  - <​WRAP><​code>​OPEN"​CAS:​ADDRESS"​ FOR INPUT AS #​1</​code>​ +
-|Устройство|CAS:​| +
-|Файл|ADDRESS| +
-|Направление|INPUT (файл, сохранённый на ленте, нужно ввести)| +
-|Номер файла|1| +
-</​WRAP>​ +
-  - <​WRAP><​code>​OPEN"​ADDRESS"​ FOR OUTPUT AS #​1</​code>​ +
-|Устройство: ​ A:  |(по умолчанию в [[msx:​disk_basic]])| +
-|Файл|ADDRESS| +
-|Направление|OUTPUT (файл должен быть создан на дискете)| +
-|Номер файла|1| +
-</​WRAP>​ +
-  - <​WRAP><​code>​OPEN"​B:​ADDRESS"​ FOR APPEND AS #​2</​code>​ +
-|Устройство|B:​| +
-|Файл|ADDRESS| +
-|Направление|APPEND (добавление к уже существующему файлу)| +
-|Номер файла|2| +
-</​WRAP>​ +
-Можно открыть файл с последовательным доступом в режиме записи,​ используя один номер файла, и в режиме чтения,​ используя другой. Однако,​ каждому номеру файла будет при этом соответствовать //свой буфер//,​ никак не связанный с другими. +
- +
-Если же Вы используете только один буфер, то для изменения режима доступа к файлу последний необходимо закрыть,​ а затем вновь открыть. Этот приём особенно удобен,​ когда Вы хотите использовать в программе в любой момент только один открытый файл (''​MAXFILES=1''​). +
- +
-<WRAP centeralign>​Однажды открытый,​ но не закрытый файл не может быть открыт повторно.</​WRAP>​ +
- +
-В противном случае компьютер сообщает:​ "File already open"​. +
- +
-//​Закрытие//​ файла позволяет Вам использовать буфер с тем же номером для открытия другого файла. Оператор,​ закрывающий файлы, выглядит так: +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-CLOSE [[#​]N1,​[#​]N2,​… ,[#]Nk] +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​CLOSE''​ — служебное слово;​ +
-  * N1, N2,…, Nk — арифметические выражения,​ целые части значений которых определяют номера контрольных буферов файлов (FCB).Эти значения должны принадлежать отрезку [0,15]. +
- +
-Оператор ''​CLOSE''​ без параметров закрывает //все// открытые ранее файлы. +
- +
-При записи данных оператор ''​CLOSE''​ обеспечивает вывод в файл,​который был открыт ранее в режиме ''​FOR OUTPUT'',​ кода конца файла EOF ("End Of File") с кодом ASCII, равным &h1A. +
- +
-==== IX.3.2. Операторы PRINT#, PRINT#n, USING. Функции LOF() и LOC() ==== +
- +
-<WRAP group  99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Да,— повторял он себе,​— если бы на борту "​Пилигрима"​ я знал все, что должен знать настоящий моряк, сколько несчастий можно было бы избежать! +
-<WRAP rightalign>​ +
-—//​Жюль Верн. Дети капитана Гранта//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-Для формирования строк файла с последовательным доступом используются операторы ''​PRINT#''​ и ''​PRINT#​USING''​. +
- +
-Оператор ''​PRINT#''​ записывается в таком виде: +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-           ⎧ └─┘ +
-PRINT #n,S ⎨  ; +
-           ​⎩ ​ , +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​PRINT''​ ("​печатать",​ "​вывести"​) — служебное слово;​ +
-  * n — арифметическое выражение,​ целая часть значения которого определяет номер контрольного буфера файла;​ +
-  * S — список арифметических и (или) строковых выражений:​ γ1,γ2,… ,γk; +
-  * └─┘ — обозначение символа пробел (%%" "​%%). +
- +
-При выполнении оператора ''​PRINT#''​ значение выражения γi (i=1,2,… ,k) последовательно байт за байтом выводится в буфер почти так же, как это делается командой ''​PRINT''​. Разница состоит лишь в трактовке зонного формата. +
- +
-Если между двумя выражениями в списке S оператора ''​PRINT#''​ разделителем является //​запятая//,​то при выводе в буфер соответствующих значений между ними помещается четырнадцать дополнительных пробелов. +
- +
-Если последним символом в операторе ''​PRINT#''​ является //​пробел//,​ то выполнение оператора ''​PRINT#''​ приводит к формированию полной строки,​ но вместе с //​меткой//​ её окончания. Иначе создаётся лишь часть строки,​ а завершается её формирование или последующими операторами ''​PRINT#'',​ или закрытием файла. +
- +
-Длина строки вместе с концевой меткой не может превысить 256 байтов,​ а данные выводятся на диск в формате ASCII и только тогда, когда заполняется буфер или закрывается файл. +
- +
-Для экономного размещения данных на диске и избежания ошибок при их считывании целесообразно список S в операторе ''​PRINT#''​ записывать в виде: +
-<​code>​ +
-                         ⎧ └─┘ +
-γ1;",";​γ2;",";​ … ;",";​γк ⎨     +
-                         ​⎩ ​ ;  +
-</​code>​ +
-В этом случае значения в создаваемой строке располагаются в //​плотном//​ формате и отделяются друг от друга запятыми. +
- +
-Будем считать,​ что информация в одном операторе ''​PRINT#''​ составляет отдельную логическую строку. Строка разбивается на //​поля//​. Каждому полю логической строки соответствует переменная из списка S. +
- +
-Так логическая строка,​ состоящая из трёх полей — фасон одежды S$, цвет одежды C$, цена одежды P — будет выведена в файл оператором +
-<​code>​ +
-         PRINT #​1,​S$;",";​C$;",";​P +
-                  ▲      ▲      ▲ +
-                  │      │      │ +
-Переменные,​ определяющие поля данной логической строки +
-</​code>​ +
- +
-Если значение какого–либо строкового выражения γi содержит символы ","​ и (или) ";",​ то в качестве разделителей можно использовать символ ";",​ задаваемый строковой функцией ''​CHR$(34)'':​ +
-<​code>​ +
-CHR$(34) γs CHR$(34) +
-</​code>​ +
- +
-{{anchor:​e0932-01}} __//​Пример 1//__ [[bibliography#​b7|[7]]]. Запись данных в файл последовательного доступа. \\ {{.examples:​0932-01.bas|}} \\ [[+tab|wmsxbpge>​0932-01.bas]] +
-<​code>​ +
-10 OPEN "​GAMES"​ FOR OUTPUT AS #1 +
-20 FOR X=1 TO 5 +
-30    INPUT"​Введите название игры";​F$:​PRINT #1,F$ +
-50 NEXT X +
-60 CLOSE #1 +
-run +
-Введите название игры? Футбол +
-Введите название игры? Гольф +
-Введите название игры? Баскетбол +
-Введите название игры? Хоккей +
-Введите название игры? Регби +
-Ok +
-</​code>​ +
- +
-Если файл с именем "​GAMES"​ уже существовал,​ то данная программа сотрёт его старое содержимое и будет писать туда заново. +
- +
-Оператор ''​PRINT#'',​ не оканчивающийся символом ","​ или ";"​ автоматически порождает печать символа ''​CHR$(13)''​ (код клавиши <​key>'​Ввод '​⏎</​key>​) . +
- +
-Этот символ попадает в буфер и в конце концов в файл, где он служит разделителем между текущей записью и записью,​ следующей за ней. +
- +
-{{anchor:​e0932-02}} __//​Пример 2//__ [[bibliography#​b5|[5]]]. Открывается новый или ранее созданный файл "​Щука"​ для вывода в него ​ \\ {{.examples:​0932-02.bas|}} \\ [[+tab|wmsxbpge>​0932-02.bas]] +
-строк от начала. Программная строка 50 позволяет сформировать в буфере одну строку. +
-<​code>​ +
-20 OPEN "​Щука"​ FOR OUTPUT AS#1 +
-30 A=5:​B$="​трава":​C=83.157 +
-50 PRINT #​1,​A;",";​B$;",";​C +
-60 CLOSE #1 +
-</​code>​ +
- +
-{{anchor:​e0932-03}} __//​Пример 3//__ [[bibliography#​b5|[5]]]. \\ Открывается ранее созданный файл "​Шука"​ для вывода в него строк от конца. Затем программная строка 50 формирует очередные строки файла.По мере заполнения буфера данные выводятся на дискету,​а за последней строкой ставится метка окончания файла (EOF). +
-\\ {{.examples:​0932-03.bas|}} \\ [[+tab|wmsxbpge>​0932-03.bas]] +
-<​code>​ +
-20 OPEN "​Щука"​ FOR APPEND AS#1 +
-30 INPUT"​A=";​A:​INPUT"​B$=";​B$:​INPUT"​C=";​C +
-50 PRINT #​1,​A;",";​B$;",";​C +
-55 IF C<>0 THEN 30 ELSE CLOSE #1 +
-</​code>​ +
- +
-{{anchor:​e0932-04}} __//​Пример 4//__ [[bibliography#​b5|[5]]]. Открывается новый или ранее созданный файл "​Карась"​ для вывода в него строк от начала и далее. Двумя командами 50 и 60 формируется строка. \\ {{.examples:​0932-04.bas|}} \\ [[+tab|wmsxbpge>​0932-04.bas]] +
-<​code>​ +
-10 CLEAR 1000:​MAXFILES=2:​OPEN "​Карась"​ FOR OUTPUT AS#2 +
-30 A$="​FLOPPY DISK":​E=45:​F=54.8 +
-50 PRINT #​2,​A$;","; ​        '​◀── Последний символ ";"​ ! +
-60 PRINT #​2,​E;",";​F ​        '​◀── Последний символ "​пробел"​ ! +
-70 CLOSE #2 +
-</​code>​ +
- +
-{{anchor:​e0932-05}} __//​Пример 5//__ [[bibliography#​b5|[5]]]. В файл "​Карп"​ от его начала с клавиатуры вводится S элементов числового массива. \\ {{.examples:​0932-05.bas|}} \\ [[+tab|wmsxbpge>​0932-05.bas]] +
-<​code>​ +
-10 MAXFILES=5:​OPEN "​Карп"​ FOR OUTPUT AS#4 +
-30 INPUT "​Количество элементов";​S +
-40 FOR K=1 TO S:INPUT M:PRINT #​4,​M;",";:​NEXT K +
-50 CLOSE #4 +
-</​code>​ +
- +
-{{anchor:​e0932-06}} __//​Пример 6//__ [[bibliography#​b5|[5]]]. При формировании строки в качестве разделителей используется символ %%"%%, задаваемый кодом ''​CHR$(34)''​. \\ {{.examples:​0932-06.bas|}} \\ [[+tab|wmsxbpge>​0932-06.bas]] +
-<​code>​ +
-20 OPEN "​Сазан"​ FOR OUTPUT AS#1 +
-30 R=123.789:​K$="​КRA,,​N;​W2"​ +
-40 I$=CHR$(34) +
-50 PRINT #​1,​R;",";​I$;​K$;​I$ +
-60 CLOSE #1 +
-</​code>​ +
- +
-Оператор ''​PRINT#,​USING''​ записывается в таком виде: +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-PRINT #n,USING T,S +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-''​PRINT'',​ ''​USING''​ — служебные слова;​ +
-  * T — строковое выражение,​ значение которого определяет формат вывода;​ +
-  * n — арифметическое выражение,​ целая часть значения которого определяет номер контрольного буфера файла;​ +
-  * S — список арифметических и (или) строковых выражений:​ γ1, γ2,…, γk. +
-При выполнении данного оператора значения выражений +
-  γi    (i=1,2,… ,k) +
-выводятся в соответствии с форматом T в буфер точно так же, как это "​делает"​ "​обычный"​ оператор ''​PRINT USING''​. +
- +
-{{anchor:​e0932-07}} __//​Пример 7//__. \\ {{.examples:​0932-07.bas|}} \\ [[+tab|wmsxbpge>​0932-07.bas]] +
-<​code>​ +
-10 CLEAR 1000:​MAXFILES=5:​DIM M(200) +
-20 OPEN "​Лещ"​ FOR OUTPUT AS#4 +
-30 INPUT"​Количество элементов";​S +
-40 FOR K=1 TO S:​X=INT(RND(1)*3000)/​99:​PRINT #4,USING "###​.##";​X:​NEXT K +
-50 CLOSE #4 +
-</​code>​ +
- +
-Однако,​ следует весьма осторожно употреблять префиксы,​ обозначающие денежные единицы (%% "​$$"​ %%, %% "​**"​ %% и %% "​**$"​ %%), так как они вызывают форматирование числовых величин как нечисловых. По этой причине числовые величины,​ снабжённые в дисковом файле такими префиксами,​ не могут быть считаны оттуда в их исходном виде. +
- +
-{{anchor:​e0932-08}} __//​Пример 8//__. \\ {{.examples:​0932-08.bas|}} \\ [[+tab|wmsxbpge>​0932-08.bas]] +
-<​code>​ +
-10 OPEN "​SAMPLE.DAT"​ FOR OUTPUT AS #1 +
-20 PRINT #​1,​USING"​$$###​.##";​99.50:​CLOSE#​1 +
-40 OPEN "​SAMPLE.DAT"​ FOR INPUT AS#1 +
-50 INPUT #​1,​A:​PRINT"​Первое значение в файле:";​A:​CLOSE#​1 +
-run +
-Первое значение в файле: 0 +
-Ok +
-</​code>​ +
- +
-Пусть открыт файл B, связанный с буфером FCBn. +
- +
-{{anchor:​lof}} +
-Функция +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-LOF(n) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​LOF''​ ("​Length Of File" — "​размер файла"​) — служебное слово;​ +
-  * n — арифметическое выражение,​ целая часть значения которого принадлежит отрезку [0,15] и определяет контрольного буфера файла, соответствующий файлу, возвращает размер файла в байтах. +
- +
-{{anchor:​loc}} +
-Функция +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-LOC(n) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​LOC''​ ("​LOCation"​ — "​определение позиции"​) — служебное слово;​ +
-  * n — арифметическое выражение,​ целая часть значения которого принадлежит отрезку [0,15] и определяет номер контрольного буфера файла, соответствующий файлу, для файлов последовательного доступа возвращает текущее количество байтов информации,​ считанных в буфер или записанных на дискету.  +
-    * Или возвращает номер //​текущей//​ номер записи,​ использованный в последнем выполненном операторе ''​[[#​PUT]]''​ или ''​[[#​GET]]''​.  +
-    * Для [[#​ramdisk|RAM–диска]] возвращает позицию в файле, начиная с номера файла. Например,​ ''​LOC''​ возвращает 0 сразу после того, как файл открыт для ввода и вывода (''​OPEN FOR INPUT''​ / ''​OPEN FOR OUTPUT''​) и возвращает длину файла сразу после того, как файл открыт для добавления (''​OPEN FOR APPEND''​). +
-==== IX.3.3. Операторы INPUT, LINE INPUT#n. Функции INPUT$ и EOF ==== +
- +
-Для чтения строк файла последовательного доступа с дискеты в оперативную память используются операторы ''​INPUT#'',​ ''​LINE INPUT#''​ и функции ''​INPUT$''​ и ''​EOF''​. +
- +
-{{anchor:​lineinput}} +
-Оператор +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-LINE INPUT #n,γ +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​LINE'',​ ''​INPUT''​ — служебные слова;​ +
-  * n — арифметическое выражение,​ целая часть значения которого определяет номер контрольного буфера файла;​ +
-  * γ — строковая переменная,​ позволяет считать очередную строку файла β, связанного с буфером n, и присвоить результат переменной γ. +
- +
-Оператор ''​LINEINPUT#'',​ считывающий одиночное строковое значение,​ позволяет решить "​проблему запятой"​. +
- +
-{{anchor:​e0933-01}} __//​Пример 1//__. \\ {{.examples:​0933-01.bas|}} \\ [[+tab|wmsxbpge>​0933-01.bas]] +
-<​code>​ +
-10 OPEN "​TEST.DAT"​ FOR OUTPUT AS #1 +
-20 PRINT #​1,"​Агибалова,​ Алевтина":​CLOSE#​1 +
-40 OPEN "​TEST.DAT"​ FOR INPUT AS#1 +
-50 LINE INPUT#​1,​A$:​PRINT"​Первое значение в файле:";​A$:​CLOSE#​1 +
-run +
-Первое значение в файле: Агибалова,​ Алевтина +
-Ok +
-</​code>​ +
- +
-{{anchor:​e0933-02}} __//​Пример 1//__. \\ {{.examples:​0933-02.bas|}} \\ [[+tab|wmsxbpge>​0933-02.bas]] +
-<​code>​ +
-10 CLEAR 1000:​MAXFILES=5:​DIM M(200) +
-20 OPEN "​LINP"​ FOR OUTPUT AS#4 +
-30 INPUT"​Количество элементов";​S +
-40 FOR K=1 TO S:PRINT #​4,​K;",";:​PRINT LOC(4);:​NEXT K:CLOSE #4 +
-70 OPEN "​LINP"​ FOR INPUT AS#4 +
-80 PRINT:PRINT LOF(4) +
-90 LINE INPUT #4,M$ +
-100 PRINT LOC(4),:​PRINT M$ +
-110 IF NOT EOF(4) THEN 90    '​Обратите внимание на данную строку! +
-120 PRINT LOF(4):​CLOSE #4 +
-</​code>​ +
- +
-{{anchor:​input}} +
-Оператор ''​INPUT#''​ записывается в виде: +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-INPUT #n,S +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​INPUT''​ — служебное слово;​ +
-  * n — арифметическое выражение,​ целая часть значения которого определяет номер контрольного буфера файла;​ +
-  * S — список переменных. +
-Опишем,​ как происходит выполнение этого оператора. +
- +
-Если очередная считываемая строка файла состоит из значений:​ α1, α2,…, αk, то в соответствующей команде ''​INPUT#''​ список S должен иметь такой вид: β1, β2,…, βk, а каждая переменная βi обязана быть того же типа,​что и значение αi. В этом случае выполнение оператора приводит к присваиваниям переменным βi значений αi. +
- +
- +
-{{anchor:​e0933-03}} __//​Пример 3//__. Чтение из файла последовательного доступа. \\ {{.examples:​0933-03.bas|}} \\ [[+tab|wmsxbpge>​0933-03.bas]] +
-<​code>​ +
-10 OPEN "​GAMES"​ FOR INPUT AS #2 +
-20 FOR X=1 TO 5:INPUT #2,G$:PRINT G$:NEXT X:CLOSE #2 +
-run +
-Футбол +
-Гольф +
-Баскетбол +
-Хоккей +
-Регби +
-Ok +
-</​code>​ +
- +
-{{anchor:​e0933-04}} __//​Пример 4//__. \\ {{.examples:​0933-04.bas|}} \\ [[+tab|wmsxbpge>​0933-04.bas]] +
-<​code>​ +
-10 OPEN "​SAMPLE.DAT"​ FOR OUTPUT AS #1 +
-20 PRINT #​1,​12,​567:​CLOSE#​1 +
-40 OPEN "​SAMPLE.DAT"​ FOR INPUT AS#1 +
-50 INPUT #​1,​A,​B:​PRINT"​Второе значение в файле:";​B:​CLOSE#​1 +
-run +
-Второе значение в файле: 567 +
-Ok +
-</​code>​ +
- +
-{{anchor:​e0933-05}} __//​Пример 5//__. \\ {{.examples:​0933-05.bas|}} \\ [[+tab|wmsxbpge>​0933-05.bas]] +
-<​code>​ +
-10 OPEN "​TEST.DAT"​ FOR OUTPUT AS #1 +
-20 PRINT #​1,"​Кремний";​14;​28.0855:​CLOSE#​1 +
-40 OPEN "​TEST.DAT"​ FOR INPUT AS#1 +
-50 FOR K%=1 TO 3:​INPUT#​1,​A$:​PRINT"​Значение номер";​K%;":";​A$:​NEXT K% +
-70 CLOSE#1 +
-run +
-Значение номер 1: Кремний 14 28.0855 +
-Input past end in 50 +
-Ok +
-</​code>​ +
- +
-При выполнении оператора ''​PRINT#''​ (строка 20) в файл записываются три различных значения,​ но поскольку в операторе они разделяются символами «;», в файл они будут заноситься без разделителей. Когда оператор ''​INPUT#''​ реализует считывание этих значений (строка 50), они все "​сливаются"​ в одно. Таким образом,​ в файле не будет существовать ни второго,​ ни третьего значений,​ поэтому при попытке чтения программой какой-либо информации за последним значением в файле фиксируется ошибка "​Считывание за пределами последнего значения"​. +
- +
-Разделителем для строковых данных может быть запятая или символ "​Возврат каретки"​. Те же самые знаки или пробелы служат для разграничения числовых величин. Существует несколько способов гарантированной расстановки +
-разделителей между отдельными значениями. Один из самых простых состоит в том, чтобы присвоить значение ","​ строковой переменной и записывать её после каждого значения в операторе ''​PRINT#''​. +
- +
-{{anchor:​e0933-06}} __//​Пример 6//__. \\ {{.examples:​0933-06.bas|}} \\ [[+tab|wmsxbpge>​0933-06.bas]] +
-<​code>​ +
-10 OPEN "​TEST.DAT"​ FOR OUTPUT AS #1 +
-15 D$=",":​PRINT#​1,"​Кремний";​D$;​14;​D$;​28.0855:​CLOSE#​1 +
-40 OPEN "​TEST.DAT"​ FOR INPUT AS#1 +
-50 FOR K%=1 TO 3:INPUT #​1,​A$:​PRINT"​Значение номер";​K%;":";​A$:​NEXT K% +
-70 CLOSE#1 +
-run +
-Значение номер 1: Кремний +
-Значение номер 2: 14 +
-Значение номер 3: 28.0855 +
-Ok +
-</​code>​ +
- +
-Отметим,​ что строковая величина в дисковом файле, могущая содержать запятую,​ должна быть записана в кавычках;​ оператор ''​INPUT#''​ обеспечивает устранение этих кавычек при считывании. +
- +
-{{anchor:​e0933-07}} __//​Пример 7//__. \\ {{.examples:​0933-07.bas|}} \\ [[+tab|wmsxbpge>​0933-07.bas]] +
-<​code>​ +
-10 OPEN "​TEST.DAT"​ FOR OUTPUT AS #1 +
-20 PRINT#​1,​CHR$(34);"​Манагуа,​ Никарагуа";​CHR$(34):​CLOSE#​1 +
-40 OPEN "​TEST.DAT"​ FOR INPUT AS#1 +
-50 INPUT#​1,​A$:​PRINT"​Первое значение в файле:";​A$:​CLOSE#​1 +
-run +
-Первое значение в файле: Манагуа,​ Никарагуа +
-Ok +
-</​code>​ +
- +
-{{anchor:​e0933-08}} __//​Пример 8//__ [[bibliography#​b7|[7]]]. //​Обновление//​ файла последовательного доступа. \\ {{.examples:​0933-08.bas|}} \\ [[+tab|wmsxbpge>​0933-08.bas]] +
-<​code>​ +
-10 OPEN "​GAMES"​ FOR INPUT AS #1   '​Открывается "​старый"​ файл +
-20 OPEN "​GAMES2"​ FOR OUTPUT AS #2 '​Открывается "​новый"​ файл (пустой) +
-30 FOR X=1 TO 5 +
-40    INPUT #1,F$ +
-50    IF F$="​Баскетбол"​ THEN F$="​Водное поло"​ +
-60    PRINT #2,F$ +
-70 NEXT X +
-80 CLOSE 1,2                      '​Оба файла закрываются +
-90 KILL"​GAMES" ​                   '​Удаление исходного файла +
-100 NAME "​GAMES2"​ AS "​GAMES" ​     '​Переименование "​нового"​ файла +
-</​code>​ +
- +
-{{anchor:​e0933-09}} __//​Пример 9//__. \\ {{.examples:​0933-09.bas|}} \\ [[+tab|wmsxbpge>​0933-09.bas]]  +
-<​code>​ +
-10 CLEAR 1000:​MAXFILES=5:​DIM M(200) +
-20 OPEN "​Шар"​ FOR OUTPUT AS#​4:​INPUT"​Количество элементов";​S +
-40 FOR K=1 TO S +
-50    X=RND(1):​Y=RND(1) +
-60    X$=CHR$(INT(RND(1)*31)+224):​Y$=CHR$(INT(RND(1)*31)+224) +
-70    PRINT #​4,​X$+Y$;",";​X;",";​Y;​ +
-80 NEXT K:CLOSE #4 +
-90 OPEN "​Шар"​ FOR INPUT AS#4 +
-100 INPUT #​4,​M$,​A,​B:​PRINT M$;A,B +
-120 IF NOT EOF(4) THEN 100 +
-130 CLOSE #4 +
-run +
-Количество элементов?​ 5 +
-ВЯ  .59521943994623 ​   .10658628050158 +
-КЩ  .73474759503023 ​   .18426812909758 +
-ЫО  .63799556899423 ​   .47041117641358 +
-ОВ  .18586284343823 ​   .12951037284958 +
-ТМ  .02818381196223 ​   .48775999680558 +
-Ok +
-</​code>​ +
-Заметим,​ что строка 100 в этом примере могла быть заменена на один из фрагментов:​ +
-а) +
-<​code>​ +
-100 INPUT #4,M$ +
-101 INPUT #4,A,B +
-</​code>​ +
- +
-b) +
-<​code>​ +
-100 INPUT #4,M$ +
-101 INPUT #4,A +
-102 INPUT #4,B +
-</​code>​ +
- +
-Для чтения очередного фиксированного количества символов из файла без учёта его разбиения на строки используется функция +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-INPUT$(m[,​[#​]n]) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​INPUT$''​ — служебное слово;​ +
-  * m — арифметическое выражение,​ целая часть значения которого должна принадлежать отрезку [1,255]; +
-  * n — номер контрольного буфера файла. +
-В любой момент работы с файлом функция ''​INPUT$''​ "​читает"​ INT(m) его очередных символов. Иными словами,​ последовательность этих символов становится значением функции ''​INPUT$()''​. При этом метки окончания строк воспринимаются так же, как любые другие символы. +
- +
-Функция ''​INPUT$''​ возвращает строку,​ содержащую заданное количество символов,​ прочитанных из файла. +
- +
-<WRAP centeralign>​Все символы,​ включая разделители,​ передаются в программу,​ за исключением специального символа с кодом ASCII &H1A, который воспринимается как признак конца файла и "​прекращает выполнение"​ функции.</​WRAP>​ +
- +
-Функция ''​INPUT$''​ предоставляет возможность последовательно выбирать символы из файла независимо от разделителей строк! +
- +
-Для полного уяснения семантики функции ''​INPUT$''​ рекомендуется "​прогнать"​ следующий пример при различных значениях параметров S и X. +
- +
-{{anchor:​e0933-10}} __//​Пример//​__10 [[bibliography#​b5|[5]]]. \\ {{.examples:​0933-10.bas|}} \\ [[+tab|wmsxbpge>​0933-10.bas]] +
-<​code>​ +
-10 CLEAR 1000:​MAXFILES=5:​DIM M(200) +
-20 OPEN "​ТОР"​ FOR OUTPUT AS#4 +
-30 INPUT "​Количество элементов";​S +
-40 FOR K=1 TO S:PRINT #​4,"​L";",";"​W";",":​NEXT K:CLOSE #4 +
-70 OPEN "​ТОР"​ FOR INPUT AS#4 +
-80 INPUT"​Длина значения в INPUT$";​X +
-90 Y=(LOF(4)-1)/​X:​ Z=(LOF(4)-1)MOD X +
-105 IF Y=0 THEN 130 +
-106 FOR K=1 TO Y +
-110 X$=INPUT$(X,#​4):​PRINT X$ +
-115 NEXT +
-120 IF Z=0 THEN 140 +
-130 PRINT INPUT$(Z,#​4) +
-140 CLOSE #4 +
-</​code>​ +
- +
-Заметим,​ что "​длину"​ файла не всегда можно определить заранее:​ представьте себе файл адресов,​ который все время приходится открывать в режиме добавления данных (''​FOR APPEND''​). Функция ''​EOF''​ позволяет Вам решить эту проблему:​ специальный символ с кодом &h1А добавляется к концу файла, когда этот файл закрывается. Этот символ помечает //​конец//​ файла. +
- +
-{{anchor:​eof}} +
-Функция ''​EOF'',​ синтаксис которой +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-EOF(n) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где:  +
-  * ''​EOF''​ ("End Of File" — "​конец файла"​) — служебное слово;​ +
-  * n — арифметическое выражение,​ целая часть значения которого определяет номер файла, сравнивает код очередного символа с кодом &h1А и возвращает:​ +
-    * -1 ("​true"​),​ если найден код конца файла, и +
-    * 0 ("​false"​) в противном случае. +
- +
-{{anchor:​e0933-11}} __//​Пример 11//__. Продемонстрируем способ использования функции ''​EOF()''​. \\ {{.examples:​0933-11.bas|}} \\ [[+tab|wmsxbpge>​0933-11.bas]] +
-<​code>​ +
-10 OPEN "​TESTF"​ FOR INPUT AS #1 +
-20 IF EOF(1) THEN 60 +
-30 INPUT #1,A:PRINT A:GOTO 20 +
-60 CLOSE #1 +
-</​code>​ +
- +
-Ниже приведены 3 схемы, определяющие последовательность операций,​ которые должны быть выполнены при перемещениях строк файлов //​последовательного доступа//​ из оперативной памяти на дискету и в обратном направлении. +
-  - <​WRAP>​Общая схема формирования строк на диске от //​начала//​ файла В: +
-  * А. В оперативной памяти резервируется буфер (оператором ''​MAXFILES=''​). +
-  * B. Открывается новый или уже существующий файл В (оператором ''​OPEN''​ с параметром ''​OUTPUT''​). +
-  * C. Формируется требуемое количество строк файла(операторами ''​PRINT#''​ или ''​PRINT#,​USING''​). На дискету из буфера они сбрасываются автоматически. +
-  * D. Файл В закрывается. +
- +
-{{anchor:​e0933-12}} __//​Пример 12//__ [[bibliography#​b7|[7]]]. \\ {{.examples:​0933-12.bas|}} \\ [[+tab|wmsxbpge>​0933-12.bas]] +
-<​code>​ +
-10 OPEN "​DRESS"​ FOR OUTPUT AS #1 +
-20 FOR X=1 TO 5 +
-30    INPUT"​Данные об одежде";​S$,​C$,​P:​PRINT #​1,​S$;",";​C$;",";​P +
-50 NEXT X:CLOSE #1 +
-run +
-Данные об одежде?​ А35,​Красный,​68.95 +
-Данные об одежде?​ A36,​Голубой,​75 +
-Данные об одежде?​ Б44,​Розовый,​105.50 +
-Данные об одежде?​ В78,​Серый,​85 +
-Данные об одежде?​ ЖД5,​Черный,​78.89 +
-Ok +
-</​code>​ +
-Отдельные сегменты программных файлов — это специфические файлы данных последовательного доступа. Поэтому программы или их фрагменты можно загружать в память как данные. Ограничимся здесь лишь двумя примерами. +
- +
-{{anchor:​e0933-13}} //​Пример 13//. Выполнение этой программы приводит к считыванию и выводу на экран всех строк программы "​Симпсон"​. \\ {{.examples:​0933-13.bas|}} \\ [[+tab|wmsxbpge>​0933-13.bas]] +
-<​code>​ +
-10 '​Чтение программного файла +
-20 OPEN "​Симпсон"​ FOR INPUT AS#1 +
-30 LINE INPUT #1,R$:PRINT R$ +
-50 IF NOT EOF(1) THEN 30 +
-60 CLOSE #1 +
-</​code>​ +
- +
-{{anchor:​e0933-14}} //​Пример 14//. Выполнение программы даёт возможность "​просмотреть"​ в той же самой программе "​Симпсон"​ строки с номерами от 30 и до 70. \\ {{.examples:​0933-14.bas|}} \\ [[+tab|wmsxbpge>​0933-14.bas]] +
-<​code>​ +
-10 '​Чтение диапазона строк +
-20 OPEN "​Симпсон"​ FOR INPUT AS#1 +
-30 LINE INPUT #1,R$ +
-40 X$=MID$(R$,​1,​2) +
-50 IF X$<"​30"​ OR X$>"​70"​ THEN 80 +
-60 PRINT R$ +
-80 IF NOT EOF(1) THEN 30 +
-90 CLOSE #1 +
-</​code>​ +
-</​WRAP>​ +
-  - <​WRAP>​Общая схема пополнения файла В строками с его //​конца//:​ +
-  * А. В оперативной памяти резервируется буфер (оператором MAXFILES=). +
-  * B. Открывается уже открытый файл В (оператором OPEN с параметром APPEND). +
-  * C. Формируется требуемое количество строк файла(операторами PRINT# или ''​PRINT#,​USING''​). На дискету из буфера они сбрасываются автоматически. +
-  * D. Файл В закрывается. +
- +
-{{anchor:​e0933-15}} __//​Пример 15//__ [[bibliography#​b7|[7]]]. Добавление в файл спортивной информации названия двух новых видов спорта. \\ {{.examples:​0933-15.bas|}} \\ [[+tab|wmsxbpge>​0933-15.bas]] +
-<​code>​ +
-10 OPEN "​GAMES"​ FOR APPEND AS#1 +
-20 PRINT #​1,"​Пинг-понг":​PRINT #​1,"​Теннис":​CLOSE #1 +
-</​code>​ +
-</​WRAP>​ +
-  - <​WRAP>​Общая схема //​считывания//​ строк с диска от начала файла В +
-  * А. В оперативной памяти резервируется буфер (оператором ''​MAXFILES''​) +
-  * В. Открывается уже существующий файл В (оператором ''​OPEN''​ с параметром ''​INPUT''​) +
-  * C. Считывается требуемое количество строк файла(операторами ''​INPUT$''​ или ''​LINEINPUT$'',​ или ''​INPUT$''​)  +
-  * D. Файл В закрывается +
- +
-{{anchor:​e0933-16}} __//​Пример 16//__ [[bibliography#​b7|[7]]]. \\ {{.examples:​0933-16.bas|}} \\ [[+tab|wmsxbpge>​0933-16.bas]] +
-<​code>​ +
-10 OPEN "​DRESS"​ FOR INPUT AS#2 +
-20 FOR X=1 TO 5 +
-30    INPUT #​2,​S$,​C$,​P:​PRINT S$,C$,P +
-50 NEXT X:CLOSE #2 +
-run +
-А35   ​Красный ​  ​68.95 +
-A36   ​Голубой ​  75 +
-Б44   ​Розовый ​  ​105.50 +
-В78   ​Серый ​    85 +
-ЖД5   ​Черный ​   78.89 +
-Ok +
-</​code>​ +
-</​WRAP>​ +
-==== IX.3.4. Примеры ==== +
- +
-  - {{anchor:​e0934-01}} <​WRAP>​Гидрометцентр ведёт статистику выпадения снега по регионам,​ для каждого из которых заведён файл последовательного доступа.Во всех файлах имеется по три элемента данных:​ имя метеоролога,​ название региона,​ количество выпавшего за зиму снега в мм. +
-  * Напишите программу ввода данных;​ заполните файлы для трёх регионов. +
-  * Просмотрите все три файла и подсчитайте средний уровень снежных осадков по трём регионам. Результат выведите на экран. +
-\\ {{.examples:​0934-01.bas|}} \\ [[+tab|wmsxbpge>​0934-01.bas]] +
-<​code>​ +
-10 MAXFILES=6:​OPEN "​region1"​ FOR OUTPUT AS #1 +
-21 OPEN "​region2"​ FOR OUTPUT AS #2:OPEN "​region3"​ FOR OUTPUT AS #3 +
-30 FOR I=1 TO 3 +
-31    PRINT "​region";​I +
-35    INPUT "​Введите количество работающих метеорологов на станции";​N +
-36 FOR E=1 TO N +
-40 INPUT "​Введите:​имя метеоролога";​I$:​INPUT "​название региона";​R$:​INPUT "​количество выпавшего за зиму снега в мм";​K +
-50  PRINT #​I,​I$;",";​R$;",";​K +
-55  NEXT E +
-60  CLOSE #I +
-70 NEXT I:CLS +
-71 OPEN "​region1"​ FOR INPUT AS #1:OPEN "​region2"​ FOR INPUT AS #2 +
-73 OPEN "​region3"​ FOR INPUT AS #3 +
-80 FOR O=1 TO 3 +
-90    S=0 +
-100   FOR E=1 TO N:INPUT #​O,​I$,​R$,​K:​S=S+K:​NEXT E +
-140   ​S=S/​N:​PRINT"​Средний уровень снежных осадков по ";​R$;"​ региону";​S +
-150   CLOSE #O +
-160 NEXT O +
-170 END +
-</​code>​ +
-</​WRAP>​ +
-  - {{anchor:​e0934-01}} <​WRAP>​Хоккейные команды "​Чёрные ястребы"​ и "​Красные крылья"​ хранят в файлах последовательного доступа имена всех своих 12 нападающих,​ число заброшенных ими шайб, сделанных голевых передач и заработанное штрафное время. +
-  * Создайте файлы "​BLACK"​ и "​RED",​ содержащие информацию о каждой из двух команд. +
-  * Ваша программа по данным,​ извлечённым из этих файлов,​ должна порождать новый файл "​ALLSTARS",​ в котором содержались бы имя, команда и сумма очков (голы + передачи) для шести лучших игроков обеих команд. Выведите имена и показатели результативности хоккеистов на экран дисплея. +
-]\ {{.examples:​0934-02.bas|}} \\ [[+tab|wmsxbpge>​0934-02.bas]] +
-<​code>​ +
-10 MAXFILES=3 +
-20 OPEN "​BLACK"​ FOR OUTPUT AS #1:OPEN "​RED"​ FOR OUTPUT AS #2 +
-25 FOR K=1 TO 2 +
-30     FOR X=1 TO 6 'В каждой команде - 6 игроков +
-40        PRINT "​Данные о команде";​K;":"​ +
-50        INPUT "​Имя нападающего";​I$:​INPUT "​Число заброшенных шайб";​F:​INPUT "​Сделанных голевых передач";​G:​INPUT "​Заработанное штрафное время";​W +
-60        PRINT #​K,​I$;",";​F;",";​G;",";​W +
-70     NEXT X +
-80     CLOSE #K +
-81 NEXT K +
-90 OPEN "​BLACK"​ FOR INPUT AS #1:OPEN "​RED"​ FOR INPUT AS #2 +
-100 OPEN "​ALLSTARS"​ FOR OUTPUT AS #3 +
-110 DIM MI$(12):DIM MK$(12):DIM MO(12) +
-115 I=1 +
-120 FOR K=1 TO 2 +
-130     FOR X=1 TO 6 +
-140        INPUT #​K,​I$,​F,​G,​W +
-145        IF K=1 THEN A$="​BLACK"​ ELSE A$="​RED"​ +
-150        O=F+G:​MI$(I)=I$:​MK$(I)=A$:​MO(I)=O:​I=I+1 +
-155     NEXT X +
-156     CLOSE #K +
-157 NEXT K +
-165 FOR I=1 TO 11 +
-166     L=I +
-170     FOR J=I+1 TO 12 +
-175        IF MO(L)<​MO(J) THEN L=J +
-176     NEXT J +
-180     SWAP MO(I),​MO(L):​SWAP MI$(I),​MI$(L):​SWAP MK$(I),​MK$(L) +
-185 NEXT I +
-190 FOR I=1 TO 6 +
-194     ​H$=MI$(I):​D$=MK$(I):​V=MO(I):​PRINT #​3,​H$;",";​D$;",";​V +
-200 NEXT I +
-210 CLOSE #3 +
-220 OPEN "​ALLSTARS"​ FOR INPUT AS#3 +
-230 FOR N=1 TO 6 +
-240    INPUT #​3,​H$,​D$,​V +
-250    PRINT "​Фамилия игрока",​H$:​PRINT "​Команда",​D$:​PRINT "​Очки",​V +
-280 NEXT N:CLOSE #3 +
-</​code>​ +
-</​WRAP>​ +
-  - {{anchor:​e0934-02}} <​WRAP>​Помогите декану факультета организовать файл академических занятий студентов,​ для чего: +
-  * создайте файл последовательного доступа и заполните его именами студентов,​ названиями академических курсов и оценками;​при этом воспользуйтесь следующими данными:<​WRAP>​ +
-^  Имя студента ​ ^  Академический курс ​ ^  Отметка ​ ^ +
-|Сергей| ​ Французский язык ​ |  5  | +
-|Дмитрий| ​ Английский язык ​ |  4  | +
-|Олег ​ |  Математика ​ |  5  | +
-|Борис| ​ Французский язык ​ |  3  | +
-|Михаил| ​ Английский язык ​ |  3  | +
-|Александр| ​ Математика ​ |  5  | +
-|Тимофей| ​ Математика ​ |  4  | +
-</​WRAP>​ +
-  * выберите "​умных"​ студентов,​ т.е. тех, кто имеет оценку выше 4,и запишите сведения о них в файл "​SMART";​ +
-  * пусть программа помогает декану формировать на основе этого файла группы углублённого обучения.По названию курса она должна выдавать список "​умных"​ студентов,​ зачисленных в такую группу. +
-\\ {{.examples:​0934-03.bas|}} \\ [[+tab|wmsxbpge>​0934-03.bas]] +
-<​code>​ +
-10 MAXFILES=2:​INPUT "​Количество студентов";​N +
-20 OPEN "​СПИСОК"​ FOR OUTPUT AS #1:OPEN "​SMART"​ FOR OUTPUT AS #2 +
-30 FOR X=1 TO N +
-50 INPUT"​Ф.И. студента:";​I$:​INPUT"​Название курса:";​K$:​INPUT"​Оценка:";​O +
-60 PRINT #​1,​I$;",";​K$;",";​O +
-70 NEXT X:CLOSE #1 +
-90 OPEN "​СПИСОК"​ FOR INPUT AS #1 +
-130 FOR X=1 TO N +
-140    INPUT #​1,​I$,​K$,​O:​IF O>=4 THEN D=D+1:PRINT #​2,​I$;",";​K$ +
-155 NEXT X:CLOSE #1:CLOSE #2 +
-220 OPEN "​SMART"​ FOR INPUT AS#2 +
-225 INPUT "​Введите название курса";​E$ +
-230 FOR I=1 TO D +
-240    INPUT #2,I$,K$:IF K$=E$ THEN PRINT I$ +
-280 NEXT I:CLOSE #2   +
-290 PRINT "​Хотите закончить Д/​Н"​ +
-300 IF INPUT$(1)="​Д"​ THEN END ELSE GOTO 220 +
-</​code>​ +
-</​WRAP>​ +
- +
-{{anchor:​open}} +
-==== IX.3.5. Вывод файлов данных на экран и принтер ==== +
- +
-Текстовые экраны 0 и 1, графические экраны,​ а также принтер могут быть объявлены устройствами вывода файлов последовательного доступа. +
- +
-//​Открытие//​ таких файлов осуществляется оператором +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-     ⎧ "​CRT:"​ +
-OPEN ⎨ "​GRP:"​ FOR OUTPUT AS[#]n +
-     ⎩ "​LPT:"​ +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​OPEN'',​ ''​FOR''​ ''​OUTPUT'',​ ''​AS''​ — служебные слова;​ +
-  * n — арифметическое выражение,​ целая часть значения которого определяет номер контрольного буфера файла;​ +
-  * ''​CRT:'',​ ''​GRP:'',​ ''​LPT:''​ — имена устройств. +
- +
-При выполнении оператора ''​OPEN''​ в качестве устройства вывода файлов назначаются:​ //​текстовые//​ экраны (''​CRT:''​),​ //​графические//​ экраны (''​GRP:''​),​ //​принтер//​ (''​LPT:''​). +
- +
-Вывод строк в любом случае осуществляется операторами ''​PRINT#''​ и ''​PRINT#,​USING''​. +
- +
-Поговорим о выводе //​программных//​ файлов на экран и принтер. +
-Используя устройства ''​CRT:'',​ ''​GRP:''​ и ''​LPT:'',​ можно выводить текст программы на экран и принтер. +
- +
-  - Команда ''​%%SAVE "​LPT:"​%%''​ предназначена для вывода текста программы на //​принтер//​. +
-  - Команда ''​%%SAVE "​CRT:"​%%''​ позволяет выводить текст программы на //​текстовый//​ экран. +
-  - Команда ''​%%SAVE "​GRP:"​%%''​ позволяет выводить текст программы на //​графический//​ экран. +
-Использование "​графического"​ оператора ''​%%SAVE "​GRP:"​%%''​ в текстовом режиме приводит к сообщению об ошибке:​ <WRAP centeralign>"​Illegal function call"​.</​WRAP>​ +
- +
-Вполне естественно,​ что команды ''​LOAD'',​ ''​RUN''​ и ''​MERGE''​ не могут "​работать"​ с устройствами ''​CRT:'',​ ''​GRP:''​ и ''​LPT:''​ ! +
- +
-__//​Примеры//​__:​ +
-  - {{anchor:​e0935-01}} {{.examples:​0935-01.bas|}} \\ [[+tab|wmsxbpge>​0935-01.bas]] <​code>​ +
-10 COLOR 1,​11,​7:​SCREEN 2:OPEN "​GRP:"​ FOR OUTPUT AS#1 +
-30 PSET (69,​80):​PRINT #​1,"​Текст на графическом экране SCREEN 2" +
-50 GOTO 50 +
-</​code>​ +
-  - {{anchor:​e0935-02}} {{.examples:​0935-02.bas|}} \\ [[+tab|wmsxbpge>​0935-02.bas]] <​code>​ +
-10 COLOR 1,​11,​7:​SCREEN 3:OPEN "​GRP:"​ FOR OUTPUT AS#1 +
-30 PSET (50,​80):​PRINT #​1,"​Текст на графическом экране SCREEN 3" +
-50 GOTO 50 +
-</​code>​ +
-  - FIXME {{anchor:​e0935-03}} Программа "​777",​ записанная на диске в формате ASCII, выводится на графический экран: \\ {{.examples:​0935-03.bas|}} \\ [[+tab|wmsxbpge>​0935-03.bas]] <​code>​ +
-10 COLOR 1,​15,​8:​SCREEN 3:​PSET(0,​10),​15:​MAXFILES=2 +
-30 OPEN "​GRP:"​ FOR OUTPUT AS#1:OPEN "​777"​ FOR OUTPUT AS#2 +
-50 LINE INPUT #2,R$:PRINT #1,R$ +
-80 IF NOT EOF(2) THEN 50 +
-90 CLOSE:GOTO 90 +
-</​code>​ +
-  - FIXME {{anchor:​e0935-04}} Файл данных последовательного доступа,​ записанный на дискете под именем "​КАРП",​ выводится на принтер. \\ {{.examples:​0935-04.bas|}} \\ [[+tab|wmsxbpge>​0935-04.bas]] <​code>​ +
-15 MAXFILES=2 +
-18 OPEN "​Карп"​ FOR OUTPUT AS#1:OPEN "​LPT:"​ FOR OUTPUT AS#2 +
-30 INPUT #1,M:PRINT #2,M; +
-35 IF NOT EOF(1) THEN 30 +
-</​code>​ +
- +
-{{anchor:​e0935-05}} __//​Пример 5//__ [[bibliography#​b76|[76]]]. Простейший //​графический//​ редактор.  +
- +
-При формировании изображения Вам могут понадобиться такие команды:​ +
-  * <​key>​L</​key>​ При нажатии этой клавиши определяется начальная точка прямой. При повторном нажатии вычерчивается прямая. +
-  * <​key>​P</​key>​ Закрашивается участок экрана. +
-  * <​key>​U</​key>​ Отменяется последняя команда. +
-  * <​key>​DEL</​key>​ Уничтожается программа,​ запущенная из памяти,​ а экран очищается. +
-  * <​key>​ESC</​key>​ Генерируется программа. +
- +
-После окончания формирования изображения текст программы на языке [[msx:​basic:​]] можно вызвать на экран, либо записать на ленту или дискету (по команде ''​SAVE''​. При необходимости программу с ленты или с дискеты можно вновь загрузить (командой ''​LOAD''​) или "​слить"​ с другой программой,​ хранящейся в памяти (командой ''​MERGE''​). +
- +
-Один из спрайтов задействуется как курсор,​ другой — в качестве маркера,​ отмечающего начало прямой,​ и ещё шесть в качестве "​координатных",​ чтобы отмечать текущие координаты курсора на экране. Когда курсор "​касается"​ одного из "​координатных"​ спрайтов,​ они пропадают. Это выполняется с использованием прерывания по ''​ON SPRITE GOSUB''​. +
-\\ FIXME {{.examples:​0935-05.bas|}} \\ [[+tab|wmsxbpge>​0935-05.bas]] +
-<​code>​ +
-10 GOTO 210 +
-30 '​Изображение дополнительных координат +
-40 ' ​          ​(подпрограмма) +
-60 PUT SPRITE 0,​(16,​P),​1,​H +
-70 PUT SPRITE 1,​(22,​P),​1,​T +
-80 PUT SPRITE 2,​(28,​P),​1,​U +
-90 PUT SPRITE 3,​(16,​P+8),​1,​H1 +
-100 PUT SPRITE 4,​(22,​P+8),​1,​T1 +
-110 PUT SPRITE 5,​(28,​P+8),​1,​U1 +
-120 RETURN +
-130 ' О с н о в н а я  программа +
-210 SCREEN 0:KEY OFF:WIDTH 38 +
-220 DEFINT A-Z +
-230 MAXFILES=2 +
-240 DIM BUF(100,​5) +
-260 ' Открытие файла +
-280 PRINT"​ЭКРАННЫЙ ГЕНЕРАТОР"​ +
-290 PRINT +
-300 PRINT"​Включите на всякий случай принтер!"​ +
-310 PRINT:​PRINT +
-320 PRINT"​Введите имя файла:";​ +
-330 A$=INPUT$(1) +
-340 IF A$=CHR$(13) AND F$<>""​THEN 390 +
-350 IF A$=CHR$(8) AND POS(0)-1>​16 THEN LOCATE POS(0)-1:​PRINT CHR$(32);:​LOCATE POS(0)-1:​F$=LEFT$(F$,​LEN(F$)-1):​GOTO 330 +
-360 IF LEN(F$)=6 THEN GOTO 330 +
-370 IF (A$>​="​A"​AND A$<​="​Z"​)OR (A$>​="​a"​ AND A$<​="​z"​)THEN F$=F$+A$ ELSE GOTO 330 +
-380 PRINT A$;:GOTO 330 +
-390 PRINT:​PRINT +
-400 PRINTUSING"​Открывается файл:&";​F$ +
-410 PRINT:​PRINT +
-420 OPEN F$ FOR OUTPUT AS#2 +
-430 PRINT USING"​Файл'&'​Открыт";​F$ +
-440 PRINT:​PRINT +
-450 PRINT"​Для продолжения нажмите любую клавишу"​ +
-460 A$=INPUT$(1) +
-470 SCREEN 2,0,0 +
-480 GOSUB 800 +
-490 IX=-1:​P=8:​Q=168:​X=128:​Y=96 +
-500 H=1:​T=2:​U=8:​H1=0:​T1=9:​U1=6 +
-510 MX=1:​MY=1:​HX=8:​HY=8:​LX=0:​LY=0 +
-520 ON SPRITE GOSUB 1780:SPRITE ON +
-530 PUT SPRITE 6,​(X,​Y),​1,​10 +
-540 GOSUB 60 +
-550 A$=INKEY$:​IF A$=""​THEN 550 +
-560 IF A$=CHR$(127)THEN IX=-1:CLS +
-570 IF A$=CHR$(27)THEN GOTO 1320 +
-580 IF A$="​P"​THEN GOSUB 910 +
-590 IF A$="​L"​THEN GOSUB 1000 +
-600 IF A$="​U"​THEN GOSUB 1160 +
-610 D=STICK(0):​IF D=0 THEN 550 +
-620 IF D=1 THEN Y=Y-MY +
-630 IF D=2 THEN Y=Y-MY:​X=X+MX +
-640 IF D=3 THEN X=X+MX +
-650 IF D=4 THEN X=X+MX:​Y=Y+MY +
-660 IF D=5 THEN Y=Y+MY +
-670 IF D=6 THEN Y=Y+MY:​X=X-MX +
-680 IF D=7 THEN X=X-MX +
-690 IF D=8 THEN X=X-MX:​Y=Y-MY +
-700 IF X>255 THEN X=255 +
-710 IF Y>191 THEN Y=191 +
-720 IF X<0 THEN X=0 +
-730 IF Y<0 THEN Y=0 +
-740 H=INT(X/​100):​T=(XMOD100)/​10:​U=X MOD10 +
-750 H1=INT(Y/​100):​T1=(YMOD100)/​10:​U1=Y MOD10 +
-760 GOTO 530 +
-780 ' О п и с а н и е  спрайтов +
-800 FOR I=0 TO 11 +
-810    S$=""​ +
-820    FOR J=1 TO 8 +
-830       READ A$:​S$=S$+CHR$(VAL("&​h"​+A$)) +
-840    NEXT +
-850    SPRITE$(I)=S$ +
-860 NEXT +
-870 RETURN +
-890 ' Подпрограмма закраски +
-910 IF POINT(X,​Y)=15 THEN RETURN +
-920 IF IX+1=500 THEN RETURN +
-930 IX=IX+1 +
-940 PAINT(X,​Y) +
-950 BUF(IX,​0)=1:​BUF(IX,​1)=X:​BUF(IX,​2)=Y +
-960 RETURN +
-980 ' Изображение ​ п р я м о й +
-1000 IF L=0 THEN 1070 +
-1010 L=0 +
-1020 LINE(X,​Y)-(BUF(IX,​1),​BUF(IX,​2)) +
-1030 IF(X=BUF(IX,​1))AND(Y=BUF(IX,​2))THEN BUF(IX,​0)=2:​PUT SPRITE 7,​(0,​209):​SPRITE ON:RETURN +
-1040 BUF(IX,​3)=X:​BUF(IX,​4)=Y +
-1050 PUT SPRITE 7,(0,209) +
-1060 BUF(IX,​0)=3:​SPRITE ON:RETURN +
-1070 IF IX+1=100 THEN RETURN +
-1080 IX=IX+1 +
-1090 L=1:SPRITE OFF +
-1100 BUF(IX,​1)=X:​BUF(IX,​2)=Y +
-1110 PUT SPRITE 7,​(X-1,​Y-2),​1,​11 +
-1120 RETURN +
-1140 '​Отмена предыдущего действия +
-1160 IX=IX-1 +
-1170 CLS +
-1180 IF IX<=-1 THEN IX=-1:​BUF(0,​0)=0:​RETURN +
-1190 FOR I=0 TO IX +
-1200     ON BUF(I,0) GOSUB 1230,​1250,​1270 +
-1210 NEXT +
-1220 RETURN +
-1230     ​PAINT(BUF(I,​1),​BUF(I,​2)) +
-1240     ​RETURN +
-1250          PSET(BUF(I,​1),​BUF(I,​2)) +
-1260          RETURN +
-1270               ​LINE(BUF(I,​1),​BUF(I,​2))-(BUF(I,​3),​BUF(I,​4)) +
-1280               ​RETURN +
-1300 '​Генерация программы +
-1320 SPRITE OFF:SCREEN 0'В оригинале оператор SPRITE OFF отсутствует! +
-1330 PRINT"​Вывод на принтер(P)"​ +
-1340 PRINT"​Вывод на экран(S)"​ +
-1350 PRINT:​PRINT +
-1360 PRINT"​Выбирайте скорее режим:"​ +
-1370 LOCATE 23,4 +
-1382 A$=INPUT$(1) +
-1390 PRINT A$ +
-1400 IF A$<>"​P"​ANDA$<>"​S"​ THEN BEEP:GOTO 1370 +
-1410 IF A$="​P"​THEN OPEN"​LPT:"​AS#​1 +
-1420 IF A$="​S"​THEN OPEN"​CRT:"​AS#​1 +
-1430 CLS +
-1450 'З а п и с ь  п р о г р а м м ы +
-1470 FOR D=1 TO 2 +
-1480    PRINT#​D,"​10 REM*"​ +
-1490    PRINT#​D,​USING"​20 REM*Имя программы:&";​F$ +
-1500    PRINT#​D,"​30 REM*"​ +
-1510    PRINT#​D,"​40 SCREEN 2" +
-1520    LN=50 +
-1530    FOR I=0 TO IX +
-1540       ​PRINT#​D,​MID$(STR$(LN),​2);​SPC(1) +
-1550       ON BUF(I,​0)GOSUB 1610,​1650,​1690 +
-1560       ​LN=LN+10 +
-1570    NEXT +
-1580    PRINT#​D,​MID$(STR$(LN),​2);​SPC(1);"​GOTO";​MID$(STR$(LN),​2) +
-1590 NEXT +
-1600 END +
-1610 T$=MID$(STR$(BUF(I,​1)),​2) +
-1620 U$=MID$(STR$(BUF(I,​2)),​2) +
-1630 PRINT#​D,​USING"​PAINT(&,&​)";​T$;​U$ +
-1640 RETURN +
-1650 T$=MID$(STR$(BUF(I,​1)),​2) +
-1660 U$=MID$(STR$(BUF(I,​2)),​2) +
-1670 PRINT#​D,​USING"​PSET(&,&​)";​T$;​U$ +
-1680 RETURN +
-1690 T$=MID$(STR$(BUF(I,​1)),​2) +
-1700 U$=MID$(STR$(BUF(I,​2)),​2) +
-1710 V$=MID$(STR$(BUF(I,​3)),​2) +
-1720 W$=MID$(STR$(BUF(I,​4)),​2) +
-1730 PRINT#​D,​USING"​LINE(&,&​)-(&,&​)";​T$;​U$,​V$,​W$ +
-1740 RETURN +
-1760 '​Подпрограмма обработка прерываний +
-1780 SPRITE OFF +
-1790 SWAP P,Q +
-1800 GOSUB 60 +
-1810 FOR D=1 TO 100:NEXT +
-1820 SPRITE ON +
-1830 RETURN +
-1840 DATA 70,​88,​98,​A8,​C8,​88,​70,​0 +
-1850 DATA 20,​60,​20,​20,​20,​20,​70,​0 +
-1860 DATA 70,​88,​08,​30,​40,​80,​F8,​0 +
-1870 DATA F8,​08,​10,​30,​08,​88,​70,​0 +
-1880 DATA 10,​20,​50,​90,​F8,​10,​10,​0 +
-1890 DATA F8,​80,​F0,​08,​08,​88,​70,​0 +
-1900 DATA 38,​40,​80,​F0,​88,​88,​70,​0 +
-1910 DATA F8,​08,​10,​20,​40,​40,​40,​0 +
-1920 DATA 70,​88,​88,​70,​88,​88,​70,​0 +
-1930 DATA 70,​88,​88,​78,​08,​10,​E0,​0 +
-1940 DATA 80,​40,​20,​10,​ 8, 4, 2,1 +
-1950 DATA 40,E0,40, 0, 0, 0, 0,0 +
-</​code>​ +
- +
-{{anchor:​ramdisk}} +
-===== IX.4. Использование RAM–диска (только для компьютеров MSX 2) ===== +
- +
-<WRAP group  99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-RAMdisk (псевдодиск) — логическое устройство,​ обеспечивающее хранение файлов в специально выделенной области оперативной памяти.Используется на микроЭВМ и ПЭВМ. +
-<WRAP rightalign>​ +
-—//​Англо–русский словарь по программированию и информатике//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-Свободное пространство памяти,​ размер которого можно определить при помощи функций ''​FRE(0)''​ и ''​FRE(%%""​%%)'', ​ автоматически распределяется интерпретатором [[msx:​basic:​]]. Когда программа слишком длинна или использует слишком много переменных,​ для временного хранения данных следует использовать либо внешние устройства (магнитные ленты, дискеты),​ либо дополнительную область памяти MSX–компьютера (так называемый RAM //​диск//​). +
- +
-Эта дополнительная область не распределяется //​автоматически//​ т.е. если программа,​ например,​ использует слишком ​ много переменных,​ это ещё не значит,​ что значения этих переменных будут автоматически перенесены в дополнительную область оперативной памяти! +
- +
-Вы сейчас убедитесь в том, что доступ к этой области осуществляется аналогично доступу к //​дисководам//​ ! +
-{{anchor:​callmemini}} +
-Оператор +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-CALL MEMINI [(R)] +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​CALL''​ ("​вызвать"​),​ ''​MEMINI''​ ("​MEMory INIcialisation"​ — "​инициализация памяти"​) — служебные слова;​ +
-  * R — арифметическое выражение,​ целая часть значения которого принимает значения от 6655 до M-32769, где M — максимальный объем RAM, инициализирует RAM диск и сообщает его текущий свободный объем. Этот оператор должен быть выполнен до первой попытки обращения к RAM диску. +
- +
-<WRAP centeralign>​Помните,​ что это обращение //​уничтожает//​ все файлы, записанные до этого на RAM диск.</​WRAP>​ +
- +
-Отметим,​ что для MSX–компьютеров с общим объёмом RAM в 128 Кбайт значение параметра R не должно превышать 98303 байт. +
- +
-Фактический же размер RAM диска (в байтах) равен значению арифметического выражения R-6399 . +
- +
-Если значение параметра R меньше указанного минимального значения,​ то RAM диск "​отключается"​ и компьютер выдаёт сообщение:​ <WRAP centeralign>"​No RAM disk"</​WRAP>,​ если же значение параметра R больше максимального значения,​ то появляется +
-сообщение о неправильном вызове функции <WRAP centeralign>"​Illegal function call"​.</​WRAP>​ +
- +
-Когда параметр R опущен,​ то его значение по умолчанию устанавливается равным максимальному,​ т.е. 98303-6399 = 91904 ≈ 92 Кбайта. +
- +
-Параметр R необходим,​ если Вы хотите использовать дополнительные области RAM как для временного хранения файлов,​ так и для других целей. +
- +
-Если же это не так, то используйте команду +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-CALL MEMINI +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-//​Имена//​ файлов,​ находящихся на RAM диске, должны включать:​ +
-  - имя устройства "​МЕМ:",​ +
-  - имя файла, состоящее не более чем из 8 символов (причём символы "​*"​ и "?"​ не могут использоваться!),​ и +
-  - расширение имени файла, состоящее из точки и не более чем из 3–х символов. Впрочем,​ расширение имени файла не обязательно;​ если оно пропущено,​ то точка также может быть опущена. +
- +
-Например:​ +
-<​code>​ +
-МЕМ:​PROGRAM1.BAS +
-MEM:HRU +
-</​code>​ +
- +
-Команды для работы с RAM диском очень похожи на команды ''​FILES'',​ ''​KILL''​ и ''​NAME''​ версии [[msx:​disk_basic]]. +
- +
-{{anchor:​callmfiles}} +
-1) Команда +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-CALL MFILES +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: ''​CALL'',​ ''​MFILES''​ — служебные слова; выводит на экран список файлов,​ записанных на RAM диске, и размер оставшегося свободного пространства. +
- +
-{{anchor:​callmkill}} +
-2) Команда +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-CALL MKILL ("​Имя файла"​) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: ''​CALL'',​ ''​MKILL''​ — служебные слова; "​стирает"​ файл с указанным именем с RAM диска. +
- +
-Обратите внимание на то, что параметр %%"​%%Имя файла%%"​%% заключается в круглые скобки! +
- +
-{{anchor:​callmname}} +
-3) Команда +
-<​code>​ +
-CALL MNAME ("​Имя старого файла"​ AS "​Имя нового файла"​) ​ , +
-</​code>​ +
-где: +
-  * ''​CALL'',​ ''​MNAME''​ — служебные слова;​ +
-  * параметр %%"​Имя старого файла"​%% обязательно должен присутствовать,​ параметр %%"​Имя нового файла"​%% может быть опущен;​ позволяет изменить имя файла. +
- +
-Перечислим теперь операторы и функции,​ которые можно использовать для работы с программными файлами и с файлами //​последовательного//​ доступа:​ +
- +
-FIXME +
-  * SAVE +
-  * LOAD +
-  * ''​[[#​MERGE]]''​ +
-  * RUN +
-  * OPEN +
-  * CLOSE +
-  * PRINT# +
-  * PRINT#​USING +
-  * INPUT# +
-  * INPUT$ +
-  * LINEINPUT#​ +
-  * ''​[[#​EOF]]''​ +
-  * ''​[[#​LOC]]''​ +
-  * ''​[[#​LOF]]''​ +
-  * ''​[[#​FPOS]]''​ +
- +
-<WRAP centeralign>​Помните,​ однако,​ что имя устройства ''​МЕМ:''​ обязано присутствовать всякий раз при упоминании имени файла!</​WRAP>​ +
- +
-Приведём несколько примеров записи операторов для работы с RAM диском:​ +
-<​code>​ +
-MERGE"​MEM:​файл"​ +
-OPEN "​MEM:​файл"​ FOR INPUT  AS#1 +
-OPEN "​MEM:​файл"​ FOR OUTPUT AS#6 +
-OPEN "​MEM:​файл"​ FOR APPEND AS#15 +
-SAVE"​MEM:​файл"​ +
-LOAD"​MEM:​файл"​ +
-RUN"​MEM:​файл"​ +
-</​code>​ +
-{{anchor:​e094-01}} __//​Пример//​__. \\ {{.examples:​094-01.bas|}} \\ [[+tab|wmsxbpge>​094-01.bas]] +
-<​code>​ +
-CALL MEMINI +
-Ok +
-10 OPEN "​MEM:​GAMES"​ FOR OUTPUT AS#1 +
-20 FOR X=1 TO 3 +
-30    INPUT"​Введите название игры";​F$:​PRINT #1,F$ +
-50 NEXT X:CLOSE #1 +
-60 PRINT"​∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗"​ +
-80 OPEN "​MEM:​GAMES"​ FOR INPUT AS#1 +
-90  FOR X=1 TO 3 +
-100    INPUT #1,F$:PRINT F$ +
-110 NEXT X +
-120 CLOSE #​1:​SAVE"​MEM:​GAMES"​ +
-run +
-Введите название игры? Футбол +
-Введите название игры? Шашки +
-Введите название игры? Хоккей +
-∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ +
-Футбол +
-Шашки +
-Хоккей +
-Ok +
-</​code>​ +
- +
-<WRAP centeralign>​Команда ''​SAVE''​ всегда записывает программу в формате ASCII, после чего она "​готова к употреблению"​ операторами ''​MERGE''​ и ''​RUN''​.</​WRAP>​ +
- +
-Отметим,​ что на RAM диске может существовать один файл с //​пустым//​ именем. Таким образом,​ синтаксически допустимы следующие конструкции:​ +
-<​code>​ +
-SAVE"​MEM:"​ +
- +
-LOAD"​MEM:"​ +
- +
-RUN"​MEM:"​ +
- +
-MERGE"​MEM:"​ +
- +
-OPEN"​MEM:"​ +
-</​code>​ +
- +
-{{anchor:​fpos}} +
-Функция +
-<​code>​ +
-FPOS(Номер файла) +
-</​code>​ +
-возвращает оставшийся объем RAM диска. +
- +
-Все остальные операторы и функции,​ перечисленные выше,​используются аналогично соответствующим конструкциям,​используемым в версии [[msx:​disk_basic]]. +
- +
-===== IX.5. Файлы на магнитной ленте ===== +
- +
-Вывод программных файлов и файлов данных из оперативной памяти на магнитную ленту и обратное считывание с ленты в память реализуется через устройство,​ называемое //​магнитофоном//​. Для идентификации файлам присваиваются //​имена//,​ конструируемые из символов алфавита языка. +
- +
-Длина имени не может превосходить 6 символов (операторы ''​SAVE'',​ ''​CSAVE''​) или 11 (оператор ''​BSAVE''​). +
- +
-Уникальность имён не обязательна. +
- +
-Работа с магнитофоном может быть организована в рамках любой версии языка [[msx:​basic:​]]. Для этих целей предусмотрены приведённые ниже команды и функции. +
- +
-{{anchor:​motor}} +
-Для управления мотором магнитофона есть специальная команда [[bibliography#​b92|[92]]]:​ +
-<​code>​ +
-MOTOR +
-</​code>​ +
-Для включения мотора используется параметр ''​ON'':​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-MOTOR ON +
-</​code>​ +
-</​WRAP>​ +
- +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-для выключения ''​OFF'':​ +
-<​code>​ +
-MOTOR OFF +
-</​code>​ +
-Команда без периметров переключает значение ''​ON''/''​OFF''​. +
- +
- +
-|''​SAVE''​|команда записи в формате ASCII программ из оперативной памяти на магнитную ленту| +
-|''​LOAD''​|команда чтения в оперативную память программ,​ записанных на магнитной ленте в формате ASCII| +
-|''​MERGE''​|команда подгрузки в память программ,​ записанных на ленте в формате ASCII| +
-|''​RUN''​|команда загрузки в память программ,​ записанных на ленте в формате ASCII, с автоматическим запуском их на счёт| +
-|''​[[#​CSAVE]]''​|команда записи во внутреннем представлении программ (см. [[202|]]) из оперативной памяти на ленту| +
-|''​[[#​CLOAD]]''​|команда чтения в оперативную память (или верификации) программ,​ записанных на ленте во внутреннем представлении (см. [[202|]])| +
-|''​[[#​BSAVE]]''​|команда записи во внутреннем представлении программных файлов или файлов данных из конкретного участка оперативной памяти на ленту| +
-|''​[[#​BLOAD]]''​|команда считывания в определённую область оперативной памяти программных файлов и файлов данных,​ записанных на ленте во внутреннем представлении (см. [[202|]])| +
-|''​OPEN''​|операторы и функции для работы с файлами данных последовательного доступа| +
-|''​CLOSE''​|:::​| +
-|''​MAXFILES=''​|:::​| +
-|''​EOF()''​|:::​| +
-|''​PRINT#''​|:::​| +
-|''​PRINT#​USING''​|:::​| +
-|''​INPUT#''​|:::​| +
-|''​LINE INPUT#''​|:::​| +
-|''​INPUT$()''​|:::​| +
- +
-Приступим к краткому описанию синтаксиса и семантики упомянутых выше средств организации файлов на магнитной ленте и работы с ними. +
- +
-==== IX.5.1. Работа с программными файлами ==== +
-FIXME +
- +
-В этом пункте описаны команды ''​SAVE'',​ ''​LOAD'',​ ''​MERGE'',​ ''​RUN''​. +
-  * А. <​WRAP>​ Команда +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-SAVE α [,A] +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​SAVE''​ — служебное слово;​ +
-  * α — строковое выражение;​ +
-записывает в формате ASCII на магнитную ленту программу из оперативной памяти. +
- +
-Имя программы формируется из первых 6 символов значения строкового выражения α. Оно должно начинаться префиксом ''​%%"​CAS:"​%%'',​ который в этом случае рассматривается как //имя устройства//​ и не учитывается при подсчёте длины α, например:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-SAVE"​CAS:​СОСНА"​ +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-   +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-SAVE"​CAS:​анкета",​A +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-Заметим,​ что имя программы может быть опущено. +
- +
-Например:​ +
-<​code>​ +
-SAVE"​CAS:"​ +
-</​code>​ +
-</​WRAP>​ +
-  * <​WRAP>​В. Выполнение команды +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-LOAD α [,R] +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​LOAD''​ — служебное слово;​ +
-  * α — строковое выражение,​ значение которого определяет имя файла;​ +
-наличие параметра R приводит к автоматическому запуску загруженной программы на счёт, начинается с закрытия всех файлов и чистки оперативной памяти от программ и данных. Далее программа,​ записанная на ленте в формате ASCII под именем,​ равным значению строкового выражения α, считывается в память. +
- +
-Например:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-LOAD"​CAS:​труба"​ +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-LOAD"​CAS:​King",​R +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-Поиск конкретной программы на ленте сопровождается индикацией сообщений обо всех "​попавшихся под руку"​ при этом файлах с другими именами,​ записанных в формате ASCII. +
- +
-Приведём пример сообщения на экране дисплея при выполнении команды ''​LOAD''​(учтите,​ что: "to skip" — "​перескочить",​ "to found" — "​находить"​):​ +
-<​code>​ +
-Skip:​PRIM1 +
-Skip:       ​◀── встретилась программа без имени +
- +
-Found:​PRIM3 +
-Found: ​     ◀── найдена и загружается программа без имени +
-</​code>​ +
-Команда +
-<​code>​ +
-LOAD"​CAS:"​ [,R] +
-</​code>​ +
-считывает в память первую встреченную на ленте программу в формате ASCII. +
-</​WRAP>​ +
-  * <​WRAP>​C. +
-<​code>​  +
-RUN α +
-</​code>​ +
-Эта команда,​ если в ней указаны имя устройства и имя программы,​ загружает и запускает на выполнение программу,​ сохранённую в формате ASCII. Она похожа на команду ''​LOAD''​ (с параметром R), за тем исключением,​ что она загружает программы только в формате ASCII и закрывает все открытые файлы. +
- +
-В обоих случаях перед загрузкой программы автоматически выполняется команда ''​NEW''​. +
- +
-''//​Пример//''​. Команда ''​RUN"​CAS:​PROG1"''​ загружает и запускает программу с именем "​PROG1",​ сохранённую на магнитной ленте командой +
-<​code>​ +
-SAVE"​CAS:​PROG1"​ +
-</​code>​ +
-</​WRAP>​ +
-  * <​WRAP>​D. ​ При выполнении команды +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-MERGE α +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​MERGE''​ — служебное слово;​ +
-  * α — строковое выражение,​ значение которого определяет имя файла, закрываются файлы и организуется "​чистка"​ оперативной памяти от данных. +
- +
-Затем, программа,​ записанная на ленте в формате ASCII под именем,​ равным значению строкового выражения α, "​сливается"​ с программой β, находящейся в памяти. При этом, если в α и β совпадают некоторые номера строк,​то +
-сохраняются лишь соответствующие строки загружаемой программы α. +
-Например:​ +
-<​code>​ +
-MERGE"​CAS:​Мама!"​ +
-</​code>​ +
- +
-Выдача сообщений на экране при поиске программы α здесь такая же,как и в случае с командой ''​LOAD''​. +
-</​WRAP>​ +
- +
-Команда +
-<​code>​ +
-MERGE"​CAS:"​ +
-</​code>​ +
-подгружает в память первую встреченную на ленте в формате ASCII программу. +
- +
-Обратите внимание на тот факт,​что программы,​ вызываемые командой ''​MERGE'',​ имеют более высокий приоритет,​ по сравнению с программами,​ находящимися в памяти компьютера. Поэтому если в объединяемых программах имеются строки с одинаковыми номерами,​ то строки программы в памяти компьютера будут заменены соответствующими строками "​добавляемой"​ программы. +
-{{anchor:​csave}} +
-  * А.<​WRAP>​ Команда (оператор) ''​CSAVE''​ "​сохраняет"​программу,​ записывая её на кассету магнитной ленты. +
-Формат оператора:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-CSAVE β;[S] +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​CSAVE''​ ("​Casette SAVE" — "​запись на кассету"​) — служебное слово;​ +
-  * β — строковое выражение,​ значение которого определяет имя файла, в имени программы допускается использование любых символов,​ причём значащими в имени являются только первые шесть символов;​ +
-  * S — арифметическое выражение,​ целая часть значения которого равна 1 или 2 и определяет скорость записи данных (по умолчанию значение параметра S равнo 1): +
-    * 1 — 1200 бод (1200 бит/​с) +
-    * 2 — 2400 бод (2400 бит/​с) +
-Скорость 2400 бод требует использования хорошего магнитофона и высококачественной ленты.Скорость работы по умолчанию может быть переопределена в операторе ''​SCREEN''​ (см.раздел V.7.). +
- +
-<WRAP centeralign>​Команда ''​CSAVE''​ "​сохраняет"​ программу во //​внутреннем//​ формате , т.е. в том виде, в каком она хранится в памяти компьютера (см. [[202|]]).</​WRAP>​ +
- +
-//​Примеры//: ​     +
-  * α) команда <​code>​CSAVE"​PROG1"</​code>​ сохраняет файл, имя которого "​PROG1",​ во внутреннем формате (см. [[202|]]) со скоростью 1200 бод (или со скоростью,​ определённой оператором ''​SCREEN''​);​ +
-  * β) команда <​code>​CSAVE"​PROG2",​2</​code>​ сохраняет файл с именем "​PROG2"​ на кассетной ленте во внутреннем формате (см. [[202|]]) со скоростью 2400 бод. +
-</​WRAP>​ +
-  * <​WRAP>​{{anchor:​cload}}B. Команда +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-CLOAD β +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​CLOAD''​ ("​Cassette LOAD" — "​загрузка с кассеты"​) — служебное слово;​ +
-  * β — строковое выражение,​ значение которого определяет имя файла, позволяет загружать программу,​ сохранённую на кассетной ленте во внутреннем формате (с помощью команды ''​CSAVE''​). Загрузка выполняется на той же скорости,​ на которой программа была сохранена. Таким образом,​ Вам не нужно повторно указывать скорость. +
- +
-Если имя программы не указано в операторе,​ то будет загружена первая же программа,​ сохранённая во внутреннем формате (см. [[202|]]). +
- +
-Если Вы указываете имя программы,​то следите за правильностью ввода имени (т.е., например,​ если Вы использовали прописные буквы при написании имени, Вы должны ввести имя программы также прописными буквами). +
- +
-<WRAP centeralign>​Заметим,​ что оператор ''​CLOAD''​ автоматически выполняет команду ''​NEW''​ перед началом загрузки в память найденной программы.</​WRAP>​ +
-<​WRAP>​ +
-  * <​WRAP>​{{anchor:​cload1}} С. Оператор ''​CLOAD?''​ проверяет правильность сохранения программы на кассетной ленте.После сохранения программы перемотайте ленту назад и введите команду +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-CLOAD? β +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​CLOAD?''​ ("​Casette LOAD verify"​ — "​загрузка с ленты"​) — служебное слово;​ +
-  * β — строковое выражение,​ значение которого определяет имя файла. +
- +
-Записанная программа,​ имя которой указано в операторе,​ сравнивается байт за байтом с текстом программы в памяти компьютера. При обнаружении несовпадения эта процедура прекращается и на экране появляется сообщение об ошибке:​ <WRAP centeralign>"​Verify error" (//"​Ошибка верификации"//​).</​WRAP>​ +
- +
-Имя программы может быть опущено. В этом случае с содержимым памяти будет сравниваться первая введённая с ленты программа. +
- +
-Если имя программы не совпадает с именем,​ указанным в операторе,​ поиск программы с указанным именем будет продолжен. На экране дисплея появится следующее сообщение:​ +
-<​code>​ +
-Skip:имя программы +
-</​code>​ +
-В нем указано имя найденной "по пути"​ программы или файла данных. +
-</​WRAP>​ +
-  * <​WRAP>​D. По команде +
-{{anchor:​bsave}} +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-BSAVE α,​β1,​β2[,​β3] +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​BSAVE''​ ("​Binary SAVE") — служебное слово;​ +
-  * α — строковое выражение;​ +
-β1,β2,β3 — арифметические выражения,​ значения которых задают адреса в RAM, содержимое оперативной памяти от β1 и до β2 записывается во внутреннем представлении (см. [[202|]]) на ленту под именем,​ равным значению строкового выражения α. Значение выражения β3 определяет адрес, с которого программа при загрузке её в память будет запускаться на счёт (по умолчанию значение β3 равно значению β1). +
- +
-Если вывод осуществляется не на дисковод А, то следует указать имя устройства. Затем укажите:​ +
-  * имя файла,​ +
-  * начальный адрес сохраняемых данных,​ +
-  * конечный адрес сохраняемых данных и, возможно,​ +
-  * адрес выполнения;​ если последний пропущен,​ то адрес, отмечающий начало данных,​ будет автоматически рассматриваться как адрес выполнения при загрузке этих данных (эта часть информации полезна только в том случае,​ если сохраняются подпрограммы на машинном языке). +
- +
-__//​Примеры//​__. +
-  * <​code>​BSAVE "​CAS:​ГОСТ",&​HF000,​ &​HF0EE</​code>​ +
-  * <​code>​BSAVE "​CAS:"​ A,​B,​C</​code>​ +
- +
-Команда ''​BSAVE''​ позволяет сохранить часть оперативной памяти на ленте или дискете. Это может быть подпрограмма на [[msx:​basic:​]],​ данные,​ подпрограммы ROM, рабочая область. +
- +
-<WRAP centeralign>​Оператором ''​BSAVE''​ может быть сохранена часть памяти между ячейками с адресами &H0 и &​HFFFF</​WRAP>​ +
- +
-На компьютерах [[msx:​msx_2]] возможна и другая форма записи оператора ''​BSAVE'':​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-BSAVE"​CAS:​ имя файла",​β1,​β2,​S +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-Этот оператор сохраняет на кассетной ленте содержимое видеопамяти. +
-</​WRAP>​ +
-  * {{anchor:​bload}}<​WRAP>​E. По команде +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-BLOAD α,​[,​R][,​β] +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​BLOAD''​ ("​Binary LOAD") — служебное слово;​ +
-  * α — строковое выражение;​ +
-  * R — параметр;​ +
-  * β — арифметическое выражение;​значение параметра β должно быть целым, оно определяет величину смещения адресов β1, β2 и β3 загрузки и запуска (по умолчанию β=0), в оперативную память загружается файл, записанный на ленте во внутреннем представлении (см. [[202|]]) под именем,​ равным значению выражения α.При наличии параметра R прочитанная программа автоматически запускается на счёт. +
- +
-//​Примеры//​. +
-  - <​code>​BLOAD "​CAS:​DD"</​code>​ +
-  - <​code>​BLOAD "​CAS:​LEN",​ &​H1500</​code>​ +
-  - <​code>​BLOAD "​CAS:​TEST",​ R</​code>​ +
-  - <​code>​BLOAD "​CAS:",​R</​code>​ +
-  - <​WRAP>​{{anchor:​e0951-05}} {{.examples:​0951-05.bas|}} \\ [[+tab|wmsxbpge>​0951-05.bas]] FIXME +
-<​code>​5 ​ '​Инициализация компьютера. +
-10 CALL NETEND '​Для компьютеров серии MSX 2 +
-20 BSAVE"​CAS:​initio",​0,​3 +
-30 BLOAD"​CAS:​initio",​R,&​HA000 +
-</​code>​ +
-</​WRAP>​ +
-В последнем примере подпрограмма ROM, расположенная между адресами &h0 и &h3, загружается в RAM по адресу &HA000 и запускается на выполнение. +
- +
-Команда ''​BLOAD''​ позволяет загрузить данные,​ сохранённые командой ''​BSAVE''​. Должно быть указано имя устройства,​ если это не дисковод А, и имя файла. Может присутствовать параметр R, если данные относятся к программе на машинном языке. В этом случае программа запустится после загрузки. Данные загружаются на то место, которое они занимали перед сохранением,​ если не указан адрес смещения. В этом случае данное число добавляется к начальному,​ конечному и адресу смещения,​ заданным в команде ''​BSAVE''​. +
- +
-На компьютерах [[msx:​msx_2]] возможна и другая форма записи оператора ''​BLOAD'':​ +
-<​code>​ +
-BLOAD"​CAS:​ имя файла",​S +
-</​code>​ +
-Содержимое файла будет скопировано в видеопамять. +
- +
-Обратите внимание,​ что ''​BLOAD''​ может использоваться в программе,​ не вызывая выполнения команды ''​NEW''​ или возврата в командный режим. Этот оператор может использоваться также для загрузки частей программы на [[msx:​basic:​]]. +
-</​WRAP>​ +
-{{anchor:​e0951-11}} __//​Пример 1//__.  +
-Приведём программу,​ которая позволяет указать начальный и конечный адреса загрузки двоичного файла. +
-\\ FIXME {{.examples:​0951-11.bas|}} \\ [[+tab|wmsxbpge>​0951-11.bas]] +
-<​code>​ +
-1 INPUT"​Имя файла";​A$ +
-10 OPEN A$ FOR INPUT AS#1 +
-20 FOR I=1 TO 7 +
-30    I$(I)=INPUT$(1,#​1) +
-40    PRINT ASC(I$(I)),​HEX$(ASC(I$(I))) +
-50 NEXT +
-60 CLOSE +
-65 IF I$(1)<>"​Ч"​ THEN PRINT"​Это не BLO-файл! ":​END +
-66 PRINT"​Вы хотите вывести адреса на принтер (д/​н)?"​ +
-67 Y$=INKEY$:​IF Y$=""​ THEN 67 +
-68 IF Y$="​д"​ OR Y$="​Д"​ THEN LPRINT A$ +
-69 A1=256*ASC(I$(3))+ASC(I$(2)) +
-70 PRINT "​Начальный адрес:";​HEX$(A1);"​ или";​A1 +
-71 IF Y$="​д"​OR Y$="​Д"​ THEN LPRINT"​Начальный адрес:";​HEX$(A1);"​ или";​A1 +
-79 A2=256*ASC(I$(5))+ASC(I$(4)) +
-80 PRINT "​Конечный адрес:";​HEX$(A2);"​ или";​A2 +
-81 IF Y$="​д"​ OR Y$="​Д"​ THEN LPRINT"​Конечный адрес:";​HEX$(A2);"​ или";​A2 +
-89 A3=256*ASC(I$(7))+ASC(I$(6)) +
-90 PRINT "​Адрес запуска:";​HEX$(A3);"​ или";​A3 +
-91 IF Y$="​д"​ OR Y$="​Д"​ THEN LPRINT"​Адрес запуска:";​HEX$(A3);"​ или";​A3 +
-</​code>​ +
- +
-//​Замечание//​. Команды ''​BSAVE''​ и ''​BLOAD''​ можно применять и для работы с произвольными дисковыми файлами (устройства ''​A:''​ и ''​B:''​). +
- +
-__//​Пример 2//__. Запись компьютерных игр с дискеты на магнитную ленту. +
-  - Загрузите программу с дискеты в оперативную память командой <​code>​BLOAD "​имя файла"</​code>​ +
-  - Включите Ваш магнитофон на запись,​ затем выполните команду<​code>​BSAVE "​CAS:​имя файла",​α,​β,​γ</​code>​ +
-где: +
-  * α — //​шестнадцатеричный//​ начальный адрес;​ +
-  * β — //​шестнадцатеричный//​ конечный адрес;​ +
-  * γ — //​шестнадцатеричный//​ адрес загрузки. +
-Значения α,β,γ Вы можете найти с помощью программы из примера 1. +
- +
-__//​Пример 3//__. Загрузка компьютерных игр с магнитной ленты в оперативную память. +
-  - Включите магнитофон +
-  - Выполните команду <​code>​BLOAD "CAS: Имя файла",​R</​code>​ +
-  - На экране появится надпись:<​code>​ Found: Имя файла (без расширения)</​code>​ +
-  - …И "​игрушка"​ запустится! +
- +
-</​WRAP>​ +
-</​WRAP>​ +
- +
-==== IX.5.2. Работа с файлами данных ==== +
- +
-Команда ''​OPEN''​ для устройства ''​CAS:''​ имеет следующий вид: +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-           ⎧ INPUT +
-OPEN β FOR ⎨         AS #n +
-           ⎩ OUTPUT +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-Здесь β должно начинаться с символов ''​ %% "​CAS:"​ %%''​ и, кроме того, отсутствует возможность,​ предоставляемая параметром APPEND для "​наращивания"​ файлов. Все остальное полностью аналогично работе с дисковыми файлами (устройства ''​A:'',​ ''​B:''​ и ''​MEM:''​). +
- +
-{{anchor:​e0952-01}} __//​Пример//​__. \\ +
-Строки 10÷30 создают файл данных на магнитной ленте. Для его считывания в память требуется запустить этот фрагмент со строки 50. +
-\\ {{.examples:​0952-01.bas|}} \\ [[+tab|wmsxbpge>​0952-01.bas]] FIXME +
-<​code>​ +
-10 OPEN"​CAS:​хи-хи"​ FOR OUTPUT AS #1 +
-20 FOR K=1 TO 500:PRINT #​1,​K;:​NEXT +
-30 CLOSE #1 +
-40 STOP +
-50 CLEAR 1000 +
-60 OPEN"​CAS:​хи-хи"​ FOR INPUT AS #1 +
-70 LINE INPUT #1,M$:PRINT M$; +
-80 IF NOT EOF(1) THEN 70 +
-90 END +
-</​code>​ +
- +
-===== IX.6. Дополнение ===== +
- +
-Три очень ​ //​полезных// ​ программы. +
- +
-{{anchor:​e096-01}} 1. Программа,​ осуществляющая посекторное копирование диска на кассету. \\ {{.examples:​096-01.bas|}} \\ [[+tab|wmsxbpge>​096-01.bas]] FIXME +
-<​code>​ +
-6 CLS:​PRINT:​PRINT"<<​Посекторное копирование диска на кассету>>":​PRINT:​PRINT +
-11 DEFINT A-Z:GOSUB 51:​I=&​H9000:​DEFUSR=I:​J=&​HA000:​DEFUSR1=J:​PRINT"​Сколько минут протягивается одна сторона кассеты ??":​INPUT CT:​PRINT:​PRINT"​С какого по какой сектор копировать S1, S2 (0-1500)??":​INPUT S1,S2 +
-16 READ D$:IF D$<>"#"​ THEN POKE I,​VAL("&​h"​+D$):​I=I+1:​GOTO 16 +
-21 DATA 2A,​51,​F3,​11,​00,​00,​01,​00,​02,​CD,​5C,​00,​C9,#​ +
-22 READ D$:IF D$<>"#"​ THEN POKE J,​VAL("&​h"​+D$):​J=J+1:​GOTO 22 +
-23 DATA 2A,​51,​F3,​11,​00,​B0,​01,​00,​02,​ED,​B0,​C9,#​ +
-31 FOR S=S1 TO S2:​D$=DSKI$(1,​S):​CLS:​U=USR(0):​LOCATE 0,17:PRINT "​Сектор N";​S:​I=USR1(0):​BSAVE"​CAS:​С"​+STR$(S),&​HB000,&​HB1FF:​GOSUB46:​IF T>CT-5 THEN GOSUB 56 +
-36 NEXT:END +
-46 GET TIME T$:KEY 2,​T$:​C1$=LEFT$(T$,​2):​C1=VAL(C1$)-C:​M1$=MID$(T$,​4,​2):​M1=VAL(M1$)-M:​T=C1*60+M1:​RETURN +
-51 GET TIME T$:​KEY1,​T$:​C$=LEFT$(T$,​2):​C=VAL(C$):​M$=MID$(T$,​4,​2):​M=VAL(M$):​RETURN +
-56 CLS:LOCATE 10,10:PRINT "​Проверь ленту":​LOCATE 10,​12:​PRINT"​Кончилась ??? (D/​N)":​SET BEEP 4,4 +
-61 BEEP:​O$=INKEY$:​IF O$=""​ THEN 61 ELSE ON INSTR("​@@@DdдДNnнН",​O$)\4 GOTO 66,76:GOTO 61 +
-66 PRINT "​Вставил новую ? (D)":​SET BEEP 3,4 +
-71 BEEP:​O$=INKEY$:​IF O$=""​ THEN 71 ELSE IF INSTR("​DdдД",​O$)THEN GOSUB 51:RETURN ELSE 71 +
-76 RETURN +
-</​code>​ +
- +
-{{anchor:​e096-02}} 2. Программа,​ осуществляющая посекторное восстановление диска с кассеты. \\ {{.examples:​096-02.bas|}} \\ [[+tab|wmsxbpge>​096-02.bas]] +
-FIXME +
-<​code>​ +
-6 CLS:​PRINT:​PRINT"<<​Посекторное восстановление диска с кассеты>>":​PRINT:​PRINT +
-11 DEFINT A-Z:GOSUB 51:​I=&​H9000:​DEFUSR=I:​J=&​HA000:​DEFUSR1=J:​PRINT"​Сколько минут протягивается одна сторона кассеты ??":​INPUT CT:​PRINT:​PRINT"​С какого по какой сектор копировать S1, S2 (0-1500) ??":​INPUT S1,S2 +
-16 READ D$:IF D$<>"#"​ THEN POKE I,​VAL("&​h"​+D$):​I=I+1:​GOTO 16 +
-21 DATA 21,​00,​B0,​11,​00,​00,​01,​00,​02,​CD,​5C,​00,​C9,#​ +
-22 READ D$:IF D$<>"#"​ THEN POKE J,​VAL("&​h"​+D$):​J=J+1:​GOTO 22 +
-23 DATA 01,​00,​02,​2A,​51,​F3,​54,​5D,​21,​00,​B0,​ED,​B0,​C9,#​ +
-31 FOR S=S1 TO S2:​BLOAD"​CAS:​С"​+STR$(S):​CLS:​U=USR(0):​LOCATE 0,​17:​PRINT"​Сектор N";​S:​I=USR1(0):​DSKO$ 1,S:GOSUB 46:IF T>CT-5 THEN GOSUB 56 +
-36 NEXT:END +
-46 GET TIME T$:KEY 2,​T$:​C1$=LEFT$(T$,​2):​C1=VAL(C1$)-C:​M1$=MID$(T$,​4,​2):​M1=VAL(M1$)-M:​T=C1*60+M1:​RETURN +
-51 GET TIME T$:KEY 1,​T$:​C$=LEFT$(T$,​2):​C=VAL(C$):​M$=MID$(T$,​4,​2):​M=VAL(M$):​RETURN +
-56 CLS:LOCATE 10,10:PRINT "​Проверь ленту":​LOCATE 10,12:PRINT "​Кончилась ??? (D/​N)":​SET BEEP 4,4 +
-61 BEEP:​O$=INKEY$:​IF O$=""​ THEN 61 ELSE ON INSTR("​@@@DdдДNnнН",​O$)\4 GOTO 66,76:GOTO 61 +
-66 PRINT "​Вставил новую ?​(D)":​SET BEEP 3,4 +
-71 BEEP:​O$=INKEY$:​IF O$=""​ THEN 71 ELSE IF INSTR("​DdдД",​O$)THEN GOSUB 51:RETURN ELSE 71 +
-76 RETURN +
-</​code>​ +
- +
-{{anchor:​e096-03}} 3. Программа,​ позволяющая определить тип файла на кассете. \\ {{.examples:​096-03.bas|}} \\ [[+tab|wmsxbpge>​096-03.bas]] +
- +
-//​Внимание//​! При наборе программы //​строго//​ соблюдайте пробелы между символами и нумерацию строк. +
- +
-FIXME +
-<​code>​ +
-1 WIDTH40:​PRINT"<<< ​ FORMAT FILES ON CASSETTE ​ >>>":​PRINT:​KEYOFF:​PRINT"<<< ​ BY LEO BOYARSKY (c) 1988  >>>":​POKE&​H80CA,​143'​ +
-2 CLEAR1000:​MAXFILES=1:​ONSTOPGOSUB15:​STOPON:​ONERRORGOTO14:​RESTORE4:​A=VARPTR(#​1):​NEW'​ +
-3 DEFFNA$(I)=RIGHT$("​000"​+HEX$(PEEK(I)+256*PEEK(I+1)),​4) +
-4 FORI=0TO8:​READX:​POKEA+I,​X:​NEXT:​DATA1,​0,​0,​0,​255,​0,​0,​0,​0'​ +
-5 DATA&​HDB,&​HC3,&​H32,&​H58,&​HD3,&​HC3,&​H74,&​H42 +
-6 PRINT:​X$=INPUT$(255,​1) +
-7 W$="":​FORI=A+9 TOA+18:​W=PEEK(I):​W$=W$+CHR$(W):​NEXT +
-8 N$="":​FORI=A+19TOA+24:​N=PEEK(I):​N$=N$+CHR$(N):​NEXT +
-9 IFW$="​сссссссссс"​THENW$="​BASIC ​ (cload)":​GOSUB11ELSEIFW$="​ЙЙЙЙЙЙЙЙЙЙ"​THENW$="​BASIC ​ ( load)":​GOSUB11ELSEIFW$="​пппппппппп"​THENW$="​OBJEKT (bload)":​GOSUB11:​I=A+25:​GOSUB12 +
-10 PRINT:​PRINT"<<< ​ Checking next file        >>>":​RUN2 +
-11 S$=" The "​+N$+"​ is "​+W$+"​ file.":​PRINTS$:​RETURN +
-12 SA$=FNA$(I):​IFNOT(("​8"<​=SA$)AND(SA$<​="​F380"​))THEN13ELSEEA$=FNA$(I+2):​IFNOT(("​8"<​=EA$)AND(EA$<​="​F380"​))THEN13ELSERA$=FNA$(I+4):​IFNOT(("​8"<​=RA$)AND(RA$<​="​F380"​))THEN13ELSES$=S$+CHR$(13)+"​Start:&​h"​+SA$+";​ End: &​h"​+EA$+";​ Run: &​h"​+RA$:​PRINTS$:​RETURN +
-13 I=I+1:​IFI>​A+255THENPRINT:​PRINT"​Don'​t check address !":​RETURNELSE12 +
-14 RESUMENEXT +
-15 KEYON:​POKE&​H80CA,​58'​ +
-16 END +
-</​code>​ +
- +
-====== Диск с примерами ====== +
- +
-{{.examples:​examples09.dsk|Загрузить образ диска}} +
- +
-[[+tab|wmsxbpged>​examples09.dsk|Открыть диск в WebMSX]] +
- +
- +
----- +
- +
-[<>​] +
- +
- +
-{{tag>​MSX BASIC Book_msxbpg}}+
msx/basic_programming_guide/09.1585743483.txt.gz · Последние изменения: 2020-04-01 15:18 (внешнее изменение)