\/d ГЛАВА IX. ФАЙЛОВЫЕ СРЕДСТВА MSX-BASIC \/d- Ф а й л (от англ. file - досье, картотека), набор данных,- 1) совокупность упорядоченных и взаимосвязанных записей, имеющая описание для идентификации отдельных записей; 2) последовательность записей, размещаемая на внешних запо- минающих устройствах (внешней памяти) и рассматриваемая в процессе пересылки и обработки как единое целое. Математический Энциклопедический Словарь В персональном компьютере "YAMAHA" предусмотрена работа с двумя версия- ми языка BASIC: MSX-BASIC и MSX-Disk-BASIC. Версия языка MSX-BASIC преду- сматривает работу только с накопителем на магнитной ленте, а в версии MSX- Disk BASIC возможно работать как с накопителем на магнитной ленте, так и с магнитными дисками. Выбор версии языка BASIC, с которой будет работать персональный компью- тер "YAMAHA", осуществляется автоматически и зависит от состава подключен- ных внешних устройств хранения информации. Версия языка MSX-BASIC "прошита" (записана, хранится) непосредственно в ROM компьютера, а версия языка MSX-Disk BASIC записана и хранится в ROM интерфейса (устройства сопряжения и согласования) дискового накопителя - д и с к о в о д а. В зависимости от того, подключен ли интерфейс (вместе с дисководом) к компьютеру или нет, и выбирается версия языка BASIC, с ко- торой мы будем работать. Если интерфейс подключен,то при включении компью- тера "работает" интерпретатор языка MSX-Disk BASIC, а если нет, то "вклю- чается" интерпретатор языка MSX-BASIC. ┌────────────────────────────────────────────────────────────────────────┐ │ Практически для учительского компьютера это делается следующим образом:│ │ нажмите кнопку RESET и в момент начальной инициализации компьютера │ │ держите нажатой клавишу SHIFT ! │ └────────────────────────────────────────────────────────────────────────┘ Будем предполагать,что Ваш компьютер имеет встроенный дисковод. В таком варианте при включении запускается MSX-Disk BASIC, а приоритетным устрой- ством внешней памяти является дисковод А:. Работая на компьютере без дисковода, Вы запускаете при включении MSX- BASIC, а приоритетным устройством является кассетный магнитофон (CAS:), имя которого может опускаться. З а м е ч а н и е. В СССР распространены две версии языка MSX-BASIC: α) версия 1.0 (на компьютерах серии MSX-1); β) версия 2.1 (на компьютерах серии MSX-2). Для определения номера версии в Вашей программе проверьте содержимое ячейки ROM с адресом &H002D: ┌───────────────┬────────────────────┐ │ Номер версии │ Содержимое ячейки │ ├───────────────┼────────────────────┤ │ 1.0 │ 0 │ ├───────────────┼────────────────────┤ │ 2.1 │ 1 │ └───────────────┴────────────────────┘ IX.1. Р а б о т а с ф а й л а м и на д и с к е т а х Под словом "д а н н ы е" мы будем подразумевать содержимое памяти ком- пьютера. Принято различать текст программы,исходные данные для работы про- граммы и результаты работы программы. Работа с внешней памятью подразумевает запись и чтение данных, размеща- емых на внешних носителях информации - кассете магнитной ленты или гибком магнитном диске (д и с к е т е). IX.1.1. Ф о р м а т и р о в а н и е д и с к е т ы Дискеты бывают следующих типов: 1) односторонние одинарной плотности (SS,SD); 2) односторонние двойной плотности (SS,DD); 3) двусторонние двойной плотности (DS,DD). Односторонность и двусторонность свидетельствует о том, имеет ли диско- вод одну или две магнитные головки, которые обеспечивают запись и считыва- ние информации с одной или двух сторон гибкого диска. Лучший способ объяс- нить понятие "плотность записи" - провести аналогию с грампластинкой: счи- тать, например, что на диске двойной плотности в два раза больше"дорожек", чем на диске одинарной плотности. И хотя память на гибком диске является магнитной и никаких, естественно, дорожек нет, на гибком диске четверной плотности может храниться в четыре раза больше информации, чем на диске одинарной плотности. Для работы с 3,5-дюймовым (8,89 см) дисководом MSX-компьютера использу- ются односторонние дискеты MF1-DD, двусторонние дискеты MF2-DD или их аналоги (слова: "диск", "дискета" и "флоппи-диск" мы будем рассматривать как синонимы). Дискета заключена в твердый пластмассовый конверт и имеет переключа- тель защиты записи и скользящую шторку для прикрытия окна, через которое организуется чтение (запись) информации. ┌────────────────────────────────────────────────────────────────┐ │ Вставлять дискету в карман (щель) дисковода и извлекать ее │ │ оттуда можно лишь при в к л ю ч е н н о м дисководе! │ └────────────────────────────────────────────────────────────────┘ Приведем некоторые характеристики дискеты MF2-DD : 1) емкость при записи: a) всего - 730 Кбайтов; b) для файлов пользователя - 713 Кбайтов; 2) плотность при записи - 8717 бит/дюйм; 3) среднее время доступа - 95 MS ; 4) максимальное количество файлов - 112. Разрешается подключать к компьютеру как одиночные, так и спаренные дис- ководы. В первом случае за устройством закрепляется переменное имя , ко- торое в любой момент времени принимает одно из конкретных значений "А" или "В". Во втором случае основной дисковод получает имя "А", а дополни- тельный - "В". Везде ниже, если это не оговорено специально, изложение ориентировано на использование одного дисковода. Для подготовки диска к работе с командами и функциями MSX-Disk BASIC необходимо осуществить специальную разметку его поверхности, называемую ф о р м а т и р о в а н и е м. Для этого дискета вставляется в карман дис- ковода, и выполняется команда ┌─────────────────────┐ │ CALL FORMAT │, └─────────────────────┘ которая вызывает на экране индикацию запроса: Drive name? (A,B) Ответом на него должен быть ввод одной из латинских букв А или В,в зависи- мости от имени устройства, в котором находится дискета. На появившийся второй запрос-"подсказку": 1 - Double Sided 2 - Single Sided ? █ пользователь обязан отреагировать вводом 1, если диск - двусторонний, или 2, если диск - односторонний. Далее по указанию Strike a key when ready █ нажмите любую клавишу. После этого начинается процесс форматирования, то есть размещение на диске управляющих меток. При этом ранее имевшаяся там информация разрушается. Правильное завершение этого процесса вызывает ин- дикацию сообщения Format complete Ok █ ┌───────────────────────────────────────────────────┐ │ Форматирование н о в ы х дискет обязательно! │ └───────────────────────────────────────────────────┘ Учтите, что именно проведенная разметка дискеты, а не ее потенциальные возможности определяет объем информации, который она может хранить, и с каким дисководом ее можно использовать! В заключении пункта дадим несколько п о л е з н ы х с о в е т о в: 1. В дискетах не предусмотрена идеальная защита записанных на них дан- ных: защитные конверты рассчитаны только на предохранение поверхности но- сителей от повреждений на коротком пути от "дискотеки" до дисковода. Особую осторожность надо соблюдать при нанесении надписей на наклейке, прикрепленной к дискете,так как даже давление карандаша или шариковой руч- ки может оказаться достаточным,чтобы через защитный конверт повредить маг- нитный слой дискеты. Во избежание порчи информации,записанной на дискетах, последние следует хранить подальше от телевизоров, видеомониторов, звоня- щих телефонов и других источников магнитных полей; 2. Для защиты файлов, сохраненных на дискете, позаботьтесь о создании копий файлов на другой дискете или на магнитной ленте; 3. Создайте архив файлов программных текстов и снабжайте дискеты и маг- нитные ленты архива этикетками; 4. Защищайте Ваши программы от неосторожного обращения путем установки переключателя защиты от записи на дискете. IX.1.2. И м е н а ф а й л о в При создании на дискете нового файла ему необходимо присвоить опреде- ленное и м я. Оно должно быть уникальным,то есть не совпадать ни с одним из уже имеющихся имен файлов, сформированных на данной дискете ранее. Имя служит для индентификации файлов и строится из последовательности символов алфавита MSX-BASIC. При этом должны учитываться следующие обсто- ятельства: 1. Количество символов имени не может превосходить 11.Попытка сформиро- вать имя большей длины ни к чему не приводит. Правые лишние символы отбра- сываются; 2. Соответствующие прописные и строчные латинские буквы, используемые в имени, равнозначны; соответствующие прописные и строчные буквы русского алфавита, используемые в имени, н е р а в н о з н а ч н ы; 3. В имени не должно быть символов: ; , + " = [ ] * \ / ? пробел 4. Символ ":" используется только при задании составных имен для разде- ления их на две части, первая из которых есть имя устройства, а вторая - имя файла. В этом случае при записи файла на диск фиксируется лишь вторая часть имени; 5. Нельзя задавать имя, состоящее из одних пробелов или начинающееся с пробела; 6. Имя не должно начинаться с точки ("."). В нем не может быть более одного такого символа и более 8 символов перед ним (если их больше восьми, то после восьмого символа устанавливается "."). Кроме того, десятичной точкой имя можно разделить на две зоны: к о - р е н ь (до точки) и р а с ш и р е н и е (после точки). Расширение со- стоит не более чем из трех символов. Номер начальной позиции корня - 1, а расширения - 10. Если пользователь фиксирует имя без расширения с количеством символов, большим 8, то компьютер автоматически разбивает его на корень и расшире- ние, вставляя в требуемое место точку. Сообщение об ошибке "Bad file name" ("Н е д о п у с т и м о е и м я ф а й л а") появляется в том случае, когда имя файла содержит более в о с ь м и сим- волов перед явно указанным расширением; если же расширение состоит более чем из т р е х символов, то интерпретатор игнорирует лишние символы. П р и м е р ы. ┌──────────────┬────────────────────┐ ───────────── │ Имя, заданное│ Представление имени│ │ пользователем│ в компьютере │ │──────────────┼────────────────────┤ │ КАТАЛОГ │ КАТАЛОГ │ │ LESSON.123 │ LESSON .123 │ │ BASIC │ BASIC │ │ВАЛ.процент │ ВАЛ .про │ │ ПРОТИВОГАЗ │ ПРОТИВОГ.АЗ │ └──────────────┴────────────────────┘ Общепринято, что расширение имени файла должно обозначать его тип. Обычно применяются следующие стандартные расширения имен: ┌────────────┬───────────────────────────────────────────────────────┐ │ Расширение │ К о м м е н т а р и й │ ├────────────┼───────────────────────────────────────────────────────┤ │ .ASM │ Исходная программа на языке ассемблера │ │ .BAK │ Резервный файл или копия некоторого файла, сделанная │ │ │ на случай повреждения оригинала │ │ .BAS │ Программа на языке BASIC │ │ .BAT │ Командный файл для пакетной обработки │ │ .C │ Исходная программа на языке C │ │ .COM │ Команда или программа, пригодные для непосредственно- │ │ │ го исполнения под управлением DOS │ │ .DAT │ Файл данных │ │ .DOC │ Файл документов (для текстовой обработки) │ │ .FOR │ Исходная программа на языке FORTRAN │ │ .LIB │ Библиотека программ │ │ .OBJ │ Скомпилированная объектная программа на машинном языке│ │ .PAS │ Исходная программа на языке PASCAL │ │ .PIC │ Данные выводимого на экран изображения │ │ .TMP │ Временный файл │ │ .TXT │ Текстовый файл │ └────────────┴───────────────────────────────────────────────────────┘ М а л е н ь к а я х и т р о с т ь. Оградить Ваш файл от посторонних взглядов можно, дав ему секретное имя, AAAAAAAA.AAA например.Секрет здесь в том, что в этом имени часть букв A из русского, а часть - из латинского алфавита, и об этом знает только хозяин файла. В большинстве случаев желательно, чтобы присвоенные файлам имена были индивидуальными и единственными и точно указывали,какой именно файл имеет- ся в виду. Но иногда удобнее обратиться сразу ко всей группе файлов, а не работать с ними по одному. Для указания р о д о в ы х имен файлов могут использоваться специаль- но предназначенные для этого знаки ? и *. В о п р о с и т е л ь н ы й знак является единственным неоднозначно интерпретированным символом в име- ни файла. Например, имена MAX1.ASM, MAX2.ASM, MAX3.ASM все соответствуют родовому имени файла MAX?.ASM, но ему не соответствует имя MAX10.ASM. З в е з д о ч к а обозначает любое количество неоднозначно интерпрети- руемых символов. Например, Zilog*.A* будет обозначать любое имя файла, ко- торое начинается с Zilog, при условии, что его расширение начинается с A. Однако звездочка имеет смысл только при использовании ее в качестве по- следнего символа имени файла или расширения. Например, родовое имя файла *CALC.BAS - это то же самое, что и имя *.BAS, которое соответствует каждо- му файлу, имеющему расширение имени *.BAS. Отметим, что *.* - родовое имя файлов с любыми именами. IX.1.3. С п р а в о ч н а я и н ф о р м а ц и я о ф а й л а х Старейшим из дошедших до нас каталогов признается список литературных произведений на шумерской гли- няной плитке, относящейся к 2000 г. до н.э. . А.Михайлов Сейчас мы расскажем Вам о довольно простых средствах для получения спи- ска имен файлов, размещенных на дискете (FILES), размера ее свободной час- ти (DSKF) и некоторой другой справочной информации. Вывод имен файлов осуществляется по команде (оператору!) ┌───────────────────┐ │ [L]FILES [I] │ , └───────────────────┘ где: FILES, LFILES ("файлы") - служебные слова; I - строковое выражение, значение которого определяет имя файла или родовое имя файлов. При выполнении этой команды без параметра I список имен всех файлов диска или индицируется на экране (если префикс L отсутствует),или распеча- тывается принтером (префикс L есть). В зависимости от типа экрана и его ширины индикация имен организуется в несколько колонок. Вывод списка фай- лов на печать проводится в 1 колонку: каждому имени отводится одна стро- ка. При отсутствии файлов на диске выдается сообщение: "File not found" ("Ф а й л не н а й д е н"). Если параметр I указан и на диске имеется файл с этим именем,то данный факт подтверждается выводом единственного имени I (в противном случае Вы прочтете неприятное сообщение: "File not found"). П р и м е р ы. FILES 100 FILES ───────────── FILES "Игры" LFILES ┌───────────────┐ Функция │ DSKF(n) │ , └───────────────┘ где: DSKF("DiSK Free"-"свободная часть диска") - служебное слово; n - арифметическое выражение, целая часть значения которого долж- на принадлежать отрезку [0,2], возвращает размер в Кбайтах свободной части дискеты. Целая часть значения n определяет имя дисковода: если значение n = 0, то Вы получите информацию о свободном месте на ди- скете, находящейся в текущем активном дисководе; если значение n = 1, то Вы получите информацию о свободном месте на ди- скете, находящейся в дисководе A; если значение n = 2, то Вы получите информацию о свободном месте на ди- скете, находящейся в дисководе B. П р и м е р ы. α) PRINT DSKF(0):PRINT DSKF(1):PRINT DSKF(2) ───────────── β) X=1:PRINT DSKF(X) γ) IF DSKF(0)>200 THEN 1000 Забегая далеко вперед, заметим,что для определения размера в байтах об- ласти дискеты, отведенной под произвольный файл, можно воспользоваться командами: ┌──────────────────────────────────────────────────────────────────┐ │ OPEN "И м я ф а й л а" FOR INPUT AS#1:PRINT LOF(1):CLOSE #1 │ └──────────────────────────────────────────────────────────────────┘ IX.1.4 О п е р а т о р ы NAME, COPY и KILL Изменение имени программного файла или файла данных производится по ко- манде (оператору) ┌───────────────────────┐ │ NAME I AS J │ , └───────────────────────┘ где: NAME("имя") - служебное слово, I - строковое выражение, значение которого определяет "старое" имя файла, J - строковое выражение, значение которого определяет "новое" имя файла. При выполнении этой команды прерывание происходит при отсутствии на дискете файла с именем I (нечего переименовывать!), при наличии на ней файла с именем J (имя J уже зарезервировано!) или при закрытой на запись дискете. В противном случае файл с именем I получает новое имя J. При задании имени J разрешено использование символов "?". Но при реаль- ном формировании имени J на дискете каждый такой символ будет заменен на элемент из соответствующей позиции имени I. П р и м е р ы. α) NAME "алфавит" AS "АЛФ" ───────────── β) name X$ as "X.1" γ) 200 NAME "PQR.XYZ" AS "?.?11" В последнем случае новое имя будет выглядеть так: Р ▲ .Х11 │ 7 пробелов Для дублирования на дисках программных файлов и файлов данных применя- ется команда (оператор) ┌─────────────────────┐ │ COPY i TO j │ , └─────────────────────┘ где: 1) COPY ("копировать"),ТО("в") - служебные слова; 2) i - строковое выражение, значение которого определяет имя исход- ного файла; 3) j - строковое выражение, значение которого определяет имя форми- руемого файла. При выполнении команды (оператора) COPY по файлу любого формата с име- нем i создается его копия с именем j. Имена i и j не должны совпадать. В том случае, когда файл с именем j уже существует на дискете, содержимое файла с именем j заменяется на содержимое файла с именем i и, естественно, "старое" содержимое файла с именем j пропадает! Если i или j - файлы данных, то они не должны быть открыты! П р и м е р ы. α) COPY "AL" TO "LA" ───────────── β) COPY "X" TO "X.1" γ) 10 SAVE "U.1" 20 FOR J=1 TO 20 30 COPY"U.1"TO"U."+MID$(STR$(J),2) 40 NEXT δ) COPY "A:ПРОБА" ТО "В:ПРОБА" Копирование всех файлов с одной дискеты на другую при наличии несколь- ких (больше двух) дисководов проводится операторами: COPY "A:*.*" TO "B:*.*" (с А в В) COPY "B:*.*" TO "A:*.*" (с В в А) На одном дисководе эта процедура и ей подобные (см.пример 4) реализу- ются по соответствующим сообщениям на экране периодической сменой дискет в кармане дисковода. Если служебное слово ТО и второй аргумент будут опущены, то файл будет скопирован на активный дисковод (обычно с B: на A:), например: COPY"b:E87.COM" . ┌────────────────┐ По команде (оператору) │ KILL I │ , где: └────────────────┘ KILL("разрушать","убивать") - служебное слово; I - строковое выражение, значение которого определяет имя файла, происходит разрушение на дискете файла с именем I и увеличение на соответ- ствующую величину размера свободной части дискеты. Фактическому разруше- нию (стиранию) подвергается лишь справочная информация о файле. Если I - имя файла данных, то при выполнении команды KILL он не должен быть открыт. П р и м е р ы. α) KILL"Бочка":KILL"R.T" ───────────── β) X$="ЮюЮ":KILL X$ γ) 100 FOR K=1 TO 25:KILL"ЦЕХ."+MID$(STR$(K),2):NEXT IX.1.5. О п е р а т о р ы LOAD, SAVE, RUN и MERGE ┌──────────────────┐ По команде (оператору): │ SAVE I [,A] │ , └──────────────────┘ где: SAVE ("сохранить") - служебное слово; I - строковое выражение, значение которого определяет имя файла, программа из оперативной памяти под именем I записывается на дискету.В за- висимости от наличия или отсутствия параметра А запись проводится соответ- ственно или в формате ASCII, или в форме внутреннего представления. Попробуем прочесть программу 10 X=1 , записанную: α) в кодах ASCII: 10 X=1 β) во внутреннем представлении (по кодам): FF 09 80 0A 00 58 EF 12 00 00 00 . ── ───▲─── ───▲─── ── ▲ ── ─▲ ───▲─── Начало ▲ │ │ ▲ │ ▲ │ └ Конец программы ┘ Адрес следу- Номер └ X = 1 ┘ Конец программы ющей строки строки (10) строки ┌───────────────────────────────────────────────────────────────────────┐ │ Если данная программа впоследствии будет погружаться в память для сли-│ │ яния с другими программными модулями, то ее необходимо записывать в │ │ коде ASCII. │ └───────────────────────────────────────────────────────────────────────┘ Заметим,что формат ASCII приводит к увеличению в несколько раз времени записи программ из оперативной памяти на дискету, а также их чтения с дис- кеты в память. К тому же для их размещения на дискете требуется приблизи- тельно на 30% больше места, чем для соответствующих программ, написанных во внутреннем представлении. При наличии на диске программного файла или файла данных с именем I и записи на него новой программы под тем же именем, старый файл пропадает и происходит изменение размера свободной части диска в соответствии с новы- ми размерами файла с именем I. П р и м е р ы. α) SAVE"PROTOOL.SYS" ───────────── β) X$="Z80.ABC":SAVE X$:SAVE"PRIMER.BAS",A γ) 10 FOR M=1 TO 30:SAVE"палата"+MID$(STR$(М),2):NEXT Для считывания программ с дискеты в оперативную память используются команды (операторы) LOAD и RUN. 1. По команде ┌───────────────┐ │ LOAD I[,R] │ , └───────────────┘ где: LOAD ("загрузка") - служебное слово; I - строковое выражение, значение которого определяет имя файла; R - необязательный параметр; прежде всего закрываются все файлы и оперативная память очищается от программ и данных. Далее программа, записанная на дискете в машинных ко- дах или формате ASCII под именем I, загружается в оперативную память. При наличии параметра R после загрузки производится запуск программы на счет. П р и м е р ы. α) LOAD"X.Y" ───────────── β) Z$=MID$(A$,5,3):LOAD Z$,R ┌──────────────────────────────────────────────────────────────┐ │ Еще раз напомним Вам, что загрузка программы "стирает" │ │ программу, находящуюся в момент загрузки в памяти компьютера.│ └──────────────────────────────────────────────────────────────┘ ┌────────────────┐ 2. По команде │ RUN I[,R] │ , └────────────────┘ где: RUN ("запуск","прогон") - служебное слово, I - строковое выражение, значение которого определяет имя файла, в оперативную память загружается и запускается на счет программа, записан- ная на диске под именем I в машинных кодах или в формате ASCII. При отсутствии параметра R перед загрузкой файла с именем I закрывают- ся все открытые файлы, и память очищается от программ и данных. При наличии параметра R из памяти удаляются программы и значения пере- менных. Однако файлы данных н е з а к р ы в а ю т с я ! П р и м е р [5]. ─────────────── 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 Приведем вид отдельного модуля, например модуля с именем "прог.А": 10 PRINT"Выполняется программа А" 20 RUN"ММF",R Интересные возможности по "соединению" программ предоставляются коман- дой (оператором!) ┌───────────────┐ │ MERGE I │ , └───────────────┘ где: MERGE("слияние") - служебное слово; I - строковое выражение, определяющее имя файла, записанного на дискете в формате ASCII. ┌────────────────────────────────────────────────────────────────┐ │ Выполнение команды MERGE начинается с закрытия всех файлов │ │ и чистки оперативной памяти от данных. │ └────────────────────────────────────────────────────────────────┘ Далее производится слияние программы А, находящейся в памяти, с про- граммным файлом, записанным на диске в формате ASCII под именем I. П р и м е р ы. α) MERGE "TTT" ───────────── β) L$="техника":MERGE L$ γ) 100 MERGE "LIST.3" Обратите внимание на тот факт,что программы, вызываемые командой MERGE, имеют более высокий приоритет по сравнению с программами, находящимися в памяти компьютера. Поэтому если в объединяемых программах имеются строки с одинаковыми номерами, то строки программы в памяти компьютера будут за- менены соответствующими строками "добавляемой" программы с именем I. Наиболее целесообразно использовать этот оператор при работе с библио- теками подпрограмм на магнитной ленте или на дискете. Покажем, как это де- лается. П р и м е р. Предположим, что программа,находящаяся в памяти,занимает ──────────── строки с 10 по 1290. Для добавления подпрограммы, назван- ной при записи на дискету "ROUT1" и занимающей строки с 10 по 190,сначала Вы должны сохранить программу, находящуюся в памяти. После этого Вы вызываете подпрограмму "ROUT1", используя команды LOAD или CLOAD. Теперь используйте команду RENUM для перенумерации строк подпрограммы, начиная, например, со строки 10000. Далее сохраните подпрограмму в формате ASCII, назвав ее новым именем, например "ROUT0", после чего повторно загрузите основную программу. Теперь выполнение команды MERGE "ROUT0" приведет к тому, что в конце текста основной программы будет добавлен текст подпрограммы с номерами строк, начинающимися с 10000. IX.2. Ф а й л ы д а н н ы х п р я м о г о д о с т у п а Я знаю, что положил это в надежное место, но теперь не могу вспомнить,в какое именно! Из диалога на приеме у врача Как мы уже отмечали (см. главу V), файл данных п р я м о г о доступа представляет собой последовательность нумерованных групп значений, называ- емых з а п и с я м и. Запись представляет собой единицу хранимой в файле информации. Размер записи зависит от решаемой Вами задачи. Запись есть совокупность сведений о некотором объекте. Она образуется из п о л е й, или элементов данных, указывающих на различные атрибуты, присущие конкретному объему. Так, если "объектами" для зубного врача являются пациенты,то каждая за- пись должна хранить информацию о каком-либо пациенте, а ее полями могут быть имя пациента, его возраст, номер телефона и число поставленных пломб. На рисунке показано зрительное представление организации файла прямого доступа. Записи с данными хранятся на дискете. При каждом запросе програм- мы на чтение или на запись должен быть указан н о м е р з а п и с и, по которому во внутреннем справочнике находится ее фактическое положение на дискете, что позволяет немедленно произвести чтение или запись. Таким об- разом осуществляется прямой доступ к записям, требующий примерно одного и того же небольшого (зависящего от скорости вращения дискеты) времени для всех записей.┌──────────────────────────────┐ ┌──────────────────┐ │ ◀───▶ Запись с данными │ Запись │ Внутренний справочник файла, │ └──────────────────┘ ────▶────◀──┤ связывающий номер записи с │ ··· Чтение│ее физическим местонахождением│ ┌──────────────────┐ │ ◀───▶ Запись с данными │ └──────────────────────────────┘ └──────────────────┘ Нумерация записей выполняется последовательно, начиная с нуля. В запись объединяются логически связанные между собой данные, и номер записи обыч- но связывается с этими данными естественным образом. Например, если записи содержат информацию о студентах некоторой группы, то в качестве номеров записей можно использовать номера студентов в спис- ке группы. Во время выполнения операции в ы в о д а для размещения записи будет выбрано место, определяемое ее номером. При выполнении операции ввода по номеру отыскивается запись и передается в память. ┌─────────────────────────────────────────────────────────────────────┐ │ П р я м о й доступ к файлу целесообразен в том случае, когда тре- │ │ буется часто менять содержимое записей и просматривать их в произ- │ │ вольном порядке. │ └─────────────────────────────────────────────────────────────────────┘ Так, бронированные места в зале театра,меняющиеся от спектакля к спектак- лю уместно хранить в файле прямого доступа. Вы, как программист, должны предусмотреть размещение каждого символа в файле прямого доступа. В этом есть смысл: можно определить структуру фай- ла в соответствии с Вашими потребностями.Вы сами регулируете поток данных в файле, и поэтому важно тщательно продумать его структуру. Разработка структуры файла не составит для Вас труда,если ясно представлять себе,что происходит в программе. Перейдем теперь к детальному описанию средств языка MSX-BASIC, предна- значенных для работы с файлами данных п р я м о г о доступа. IX.2.1. К о н т р о л ь н ы е б у ф е р ы ф а й л о в ┌───────────────┐ Оператор │ MAXFILES=A │ , └───────────────┘ где: MAX, FILES - служебные слова; А - арифметическое выражение, целая часть значения которого принад- лежит отрезку [0,15], резервирует А+1 участок оперативной памяти для последующего в р е м е н - н о г о хранения записей конкретных файлов. Например: 10 MAXFILES=5 50 MAXFILES=X+Y MAXFILES=3 Эти участки называются б у ф е р а м и или, более полно, к о н т - р о л ь н ы м и б у ф е р а м и файлов ("Field Control Buffers" - FCB) и обозначаются: FCB 0, FCB 1,... . ┌────────────────────────────────────────────────────────────────────┐ │ Каждый FCB занимает 265 байтов, из которых 9 байтов предназначены │ │ для управляющей информации, а 256 байтов - для данных. │ └────────────────────────────────────────────────────────────────────┘ Следует иметь в виду,что FCB0 и FCB1 объявлены по умолчанию и что FCB0 используется многими операторами (SAVE, LOAD, MERGE, RUN и т.п.). При выполнении оператора MAXFILES= кроме резервирования буферов произ- водится "чистка" значений переменных и закрытие всех ранее открытых фай- лов данных. При выполнении операции ч т е н и я запись из файла помещается в кон- трольный буфер файла, а при выполнении операции вывода, наоборот, содержи- мое буфера переносится в файл, в область, отведенную для записи с указан- ным номером. После выполнения операции чтения данные необходимо выбирать из буфера файла, а перед выполнением операции в ы в о д а данные должны быть поме- щены в буфер файла. ┌──────────────────────┐ Функция │ VARPTR(#n) │ , └──────────────────────┘ где: VARPTR("VARiable PoinTeR"-"указатель переменной") - служебное слово; n - арифметическое выражение, целая часть значения которого определя- ет номер FCB (от 0 до значения выражения, стоящего в правой части операто- ра MAXFILES= ), возвращает а д р е с X байта, начиная с которого расположен в памяти FCBn. Если файл не существует, то выдается сообщение об ошибке: "Illegal function call". Приведем простейший пример: 10 MAXFILES=2:X=VARPTR(#0):Y=VARPTR(#1):Z=VARPTR(#2) 20 PRINT Y-X;Z-Y run 265 265 Ok Взгляните на схему расположения информации в FCBn : Управляющая информация ────┐ Д а н н ы е ┌───┬───┬─▼─┬───┬───┬───┬───┐ │▧▧▧│▧▧▧│···│▧▧▧│███│···│███│ └───┴───┴───┴───┴───┴───┴───┘ Адреса ──▶ X X+1 X+8 X+9 X+264 ▲ │ Байт, адрес которого возвращает функция VARPTR(#n) К о н т р о л ь н ы й б у ф е р ф а й л а (FCB) ┌─────┬────────┬──────────────────────────────────────┐ │Номер│ И м я │ С о д е р ж и м о е │ │байта│ байта │ б а й т а │ ├─────┼────────┼──────────────────────────────────────┤ │ X │ FL.MOD │ Тип файла: │ │ │ │ 1 - OPEN FOR INPUT │ │ │ │ 2 - OPEN FOR OUTPUT │ │ │ │ 2 - OPEN FOR APPEND (для диска) │ │ │ │ 4 - файл прямого доступа (для диска) │ │ │ │ 4 - файл последовательного доступа, │ │ │ │ открытый для чтения и для записи, │ │ │ │ например OPEN "COM:" AS#1 │ │ │ │ 8 - OPEN FOR APPEND │ │ │ │ (для устройства MEM:) │ ├─────┼────────┼──────────────────────────────────────┤ │ X+1 │ FL.FCA ◀─┐ Ссылка на область памяти, в которой│ ┌───────┤ 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-1) │ │ │ │ │ &hC0 - устройство MEM: │ │ ├─────┼────────┼──────────────────────────────────────┤ │ │ X+5 │ FL.SLB │ ? │ │ │ X+6 │ FL.BPS │ ? │ │ │ X+7 │ FL.FLG │ ? │ │ │ X+8 │ FL.OPS │ ? │ │ ├─────┼────────┼──────────────────────────────────────┤ │ │ X+9 │ FL.BUF │ Содержимое записи файла (256 байтов) │ │ └─────┴────────┴──────────────────────────────────────┘ │ С п е ц и ф и к а ц и я ф а й л а │ ┌─────┬────────────────────────────────────────────────┬──────────┐ │ │Номер│ С о д е р ж и м о е │Количество│ │ │байта│ б а й т а │ байтов │ │ ├─────┼────────────────────────────────────────────────┼──────────┤ └──▶│ +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 │ Номер случайной записи для файла прямого доступа │ │ +34 │ (байты 33,34,35 - если размер записи больше 63;│ 4 │ │ +35 │ байты 33,34,35,36 - если размер записи меньше │ │ │ +36 │ 64) │ │ └─────┴────────────────────────────────────────────────┴──────────┘ IX.2.2. О п е р а т о р ы OPEN и CLOSE Для работы с файлами данных,уже существующими на дискетах или вновь ор- ганизуемыми, необходимо произвести их о т к р ы т и е . Делается это оператором ┌──────────────────────────────┐ │ OPEN B AS[#]n [LEN=m] │ , └──────────────────────────────┘ где: OPEN("открыть"), LEN("LENgth"-"длина") - служебные слова; B - строковое выражение, значение которого определяет имя файла; n,m - арифметические выражения, целые части значений которых опреде- ляют соответственно н о м е р контрольного буфера файла и д л и н у его записи в байтах; целая часть значения n должна принадлежать отрезку [0,6], так как дис- ковод может одновременно работать только с с е м ь ю различными файлами; целая часть значения m должна принадлежать отрезку [1,256] (по умолча- нию значение m равно 256). Все записи файла с п р я м ы м доступом имеют одинаковую длину, кото- рая (в байтах) задается параметром m . Это значение определяет способ раз- биения на записи дискового пространства, отведенного для файла. Например, если длина записи равна 50,то 6-я запись будет располагаться со смещением 300 (50╳6) от начала файла; # - необязательный символ, никак не влияющий на выполнение оператора OPEN . При выполнении оператора OPEN файлу с именем В назначается для работы контрольный буфер с номером n. Кроме того: α) с дискеты в буфер заносится управляющая информация о файле (если файл с именем B уже существует) или β) эта информация создается на дискете (если файл с именем В формирует- ся заново). ┌──────────────────────────────────────────────────────────────┐ │ Вся эта процедура и называется о т к р ы т и е м файла. │ └──────────────────────────────────────────────────────────────┘ Отметим, что один файл В не может быть открыт сразу по нескольким FCB! Например: 10 OPEN "А" AS#1 90 OPEN "klukva" AS#1 LEN=50 MAXFILES=2:OPEN"Старт"AS#2 MAXFILES=5:OPEN"Финиш"AS#3 LEN=100 ┌──────────────────────────────────────────────────────────────┐ │ Оператор OPEN открывает файл с п р я м ы м доступом, если │ │ спецификации режимов FOR INPUT, OUTPUT или APPEND опущены. │ └──────────────────────────────────────────────────────────────┘ Если программа закончит запись в файл, а в буфере останутся некоторые, не записанные на дискету данные, программа должна тем или иным способом все же завершить перепись содержимого буфера. Сделать это можно с помощью оператора з а к р ы т и я файла, к изучению которого мы и приступаем. ┌───────────────────────────────────┐ Оператор │ CLOSE [[#]N1,[#]N2,...,[#]Nk] │ , └───────────────────────────────────┘ где: CLOSE ("to close"-"закрывать") - служебное слово; N1,N2,...,Nk - арифметические выражения, целые части значений кото- рых должны принадлежать отрезку [0,15], организует з а к р ы т и е открытых с помощью оператора OPEN файлов,име- ющих номера контрольных буферов файлов,равных значениям выражений: N1, N2,..., Nk . Оператор CLOSE без параметров закрывает в с е открытые на данный мо- мент файлы данных. Однако большинство программистов предпочитают иметь гарантированный точный результат работы оператора CLOSE и поэтому указывают в нем номера файлов в явном виде. З а к р ы т ы й файл становится недоступным для формирования новых или обновления оператором PUT уже имеющихся записей. Приведем примеры синтаксиса оператора CLOSE : CLOSE CLOSE #0 CLOSE 1.5,7 ┌───────────────────────────────────────────────────────────────────┐ │ Заметим, что закрытие всех ранее открытых файлов происходит также │ │ при выполнении операторов END, CLEAR, LOAD, MAXFILES=, NEW и │ │ любом и з м е н е н и и текста программы ! │ └───────────────────────────────────────────────────────────────────┘ Пока файл не закрыт, существует опасность, что прекращение работы про- граммы - из-за ошибки пользователя, отключения электроэнергии или ошибки в программе - приведет к утрате данных или даже к повреждению дискеты. Опыт подсказывает, что желательно закрывать файл, как только исчезнет не- обходимость в том, чтобы он был открыт. IX.2.3. О п е р а т о р FIELD Как мы уже отмечали,под каждый контрольный буфер файла (FCB) отводится 265 байтов, 256 из которых непосредственно предназначены для временного хранения з а п и с и файла. Перед началом непосредственной работы с контрольным буфером файла необ- ходимо произвести его разбиение на отдельные п о л я для формирования в них конкретных значений. Делается это при помощи оператора ┌─────────────────────────────────────────────────────┐ │ FIELD [#]n, M1 AS γ1, M2 AS γ2, ..., Mk AS γk │ , └─────────────────────────────────────────────────────┘ где: FIELD ("field"-"поле") - служебное слово; n - арифметическое выражение, целая часть значения которого опреде- ляет номер контрольного буфера файла; M1,M2,...,Mk - целые числа. Учтите, что суммарная длина всех объявляемых в операторе FIELD полей не должна превосходить длины записи,установленной оператором OPEN. Нарушение этого правила приводит к ошибке; γ1,γ2,...,γk - строковые переменные (простые или с индексами), назы- ваемые б у ф е р н ы м и переменными; # - необязательный символ,никак не влияющий на выполнение оператора. При выполнении команды FIELD производится задание формата записи. Это выражается в выделении каждому значению буферной переменной γs п о л я из Ms байтов (s=1,2,...k). Ни одну из буферных переменных оператора FIELD нельзя использовать ни в каких модификациях оператора INPUT и ни одной из них нельзя присваивать значение оператором LET. Нарушение любого из этих правил приводит к утра- те соответствия, установленного оператором FIELD, вследствие чего програм- ма не может больше использовать такую переменную для занесения нужных зна- чений в записи файла или для их извлечения. Разбиение FCB на поля оператором FIELD покажем на рисунке: Управляющая информация─┐ M1 M2 ··· Mk (9 байтов) ┌────▼───┬─────────┬─────┬───┬───────────┐ │████████│ │ │···│ │ └────────┴────▲────┴──▲──┴───┴─────▲─────┘ │ │ │ Значения ───▶ γ1 γ2 ··· γk Например, оператор FIELD #1,200 AS X$,12 AS Y$ отводит 200 байтов для переменной X$ и 12 байтов - для переменной Y$. ┌─────────────────────────────────────────────────────────────────┐ │ Заметим, что этот оператор будет выполнен только в том случае, │ │ если файл был предварительно открыт. │ └─────────────────────────────────────────────────────────────────┘ П р и м е р 1. В качестве примера рассмотрим файл с прямым доступом,со- ───────────── держащий информацию о личной библиотеке. Каждая запись содержит следующую информацию: 1) номер книги (2 байта); 2) фамилию автора книги (15 байтов); 3) название книги (30 байтов); 4) признак наличия книги (1 байт); 5) информацию о читателе, взявшем книгу (22 байта); 6) дату выдачи книги (10 байтов). Для открытия этого файла и описания структуры записи можно использо- вать следующие операторы: 10 OPEN "Библтека" AS#1 LEN=80 'В имени - не более 8 символов! 20 FIELD #1,2 AS NUMBER$,15 AS AUTHOR$,30 AS BOOK$,1 AS CODE$, 22 AS R ADER$,10 AS DATE$ Отметим, что разрешается использовать несколько команд FIELD с разными форматами для одного и того же буфера n. Всегда действует то разбиение FCBn на поля, которое предложено последней выполненной командой FIELD. П р и м е р 2. ───────────── 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$ ┌─────────────────────────────────────────────────────────────────┐ │ Оператор FIELD должен выполняться перед обращениями к файлу с │ │ помощью операторов PUT и GET (см. раздел IX.2.6). │ └─────────────────────────────────────────────────────────────────┘ Прежде чем обратиться к файлу, Вы должны продумать, какие данные будут составлять записи, каковы их тип и длина (размер). В результате Вы получи- те документ, часто называемый л о г и ч е с к о й с т р у к т у р о й ф а й л а. С ним Вам предстоит работать в течение всего времени "жизни" файла. Поскольку в этом документе указано число байтов, отведенное под каждую запись, можно заранее установить количество байтов, которое потре- буется на дискете для конкретного файла, а так как известен и тип применя- емых данных, то становится очевидным, какие придется вводить переменные. Важно отметить,что при известной логической структуре файла его в дальней- шем могут использовать другие программы. На рисунке изображена структура записи в файле и дан расчет размера файла для 24 записей о пловцах. Каждая запись содержит поля для имени пло- вца, клуба,к которому он принадлежит, дисциплины, в которой он выступает, а также поля для его возраста и лучшего показанного результата. ┌───────────────────────────────────────────────────────────────────────┐ │ И м я ф а й л а: SWIMMER . Т и п ф а й л а: прямого доступа . │ │ С о д е р ж и м о е: 24 записи о пловцах . │ ├──────────────┬────────────────────────┬──────────────────┬────────────┤ │Имя переменной│ О п и с а н и е │Д л и н а п о л я│ Т и п │ │ │ п о л я │ (б а й т) │ д а н н ы х│ ├──────────────┼────────────────────────┼──────────────────┼────────────┤ │ N$ │ Имя пловца │ 30 │30 символов │ │ T$ │ Принадлежность к клубу │ 20 │20 символов │ │ E$ │ Дисциплина │ 8 │ 8 символов │ │ A$ │ Возраст │ 2 │Целое число │ │ T │ Лучший результат │ 4 │ Вещ. число │ └──────────────┴────────────────────────┴──────────────────┴────────────┘ Итого: 64 Длина и тип каждого поля указаны вместе с переменными, которые в Вашей программе будут хранить данные, извлеченные из записей. Совершенно необя- зательно использовать одни и те же переменные во всех программах, обращаю- щихся к этому файлу, однако такое единообразие позволит легче проследить ход обработки данных в любой программе. Еще раз подчеркнем, что длина записи в файле с прямым доступом п о - с т о я н н а . Она определяется при его создании, и каждому полю выделя- ется внутри записи строго определенное место.Возможные значения полей дол- жны умещаться в этом заранее отведенном объеме памяти. Если это не проду- мано заблаговременно, то при выполнении программы чрезмерно "длинные" зна- чения подвергаются усечению, а "короткие" дополняются пустующими ячейками памяти. В целях минимизации нежелательного усечения размер каждого поля обычно выбирается достаточно большим, чтобы вместить самую большую возмож- ную величину. IX.2.4. О п е р а т о р ы LSET и RSET Напомним Вам, что команда FIELD определяет формат записи файла и набор буферных переменных. Далее буферные переменные не могут использоваться в операторах LET, INPUT, LINE INPUT. При формировании в памяти конкретной записи значения буферным перемен- ным из FIELD присваиваются операторами: ┌──────────────────┐ │ LSET γ=β │ │ RSET γ=β │ , └──────────────────┘ где: LSET ("Left SET" - "поместить слева"), RSET ("Right SET" - "поместить справа") - служебные слова; γ - имя буферной переменной; β - строковое выражение (β≠γ). Пусть буферной переменной γ отведено в буфере поле размером m байтов. Выполнение оператора LSET начинается с вычисления значения выражения β. Далее, если это необходимо, его длина приводится к величине m за счет отбрасывания лишних п р а в ы х символов или добавления справа недостаю- щего количества пробелов. Полученное значение присваивается буферной пере- менной γ и размещается в соответствующем поле буфера файла. Оператор RSET выполняется почти так же, как и оператор LSET.Разница со- стоит в том, что при выравнивании значения β до длины m возможные недоста- ющие пробелы добавляются к нему не справа, а с л е в а. Неиспользованные байты заполняются пробелами. Таким образом, операторы LSET и RSET гаранти- руют, что длина значения переменной будет приведена в соответствие с дли- ной, указанной в операторе FIELD. П р и м е р 1. 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 байтов П р и м е р 2. Приведем фрагмент программы, в котором формируется за- ───────────── пись файла, содержащего информацию о личной библиотеке. В буфер заносится информация о романе Л.Н.Толстого "Война и мир". Структу- ра записи была рассмотрена ранее. 10 OPEN "Библтека" AS#1 LEN=80 20 FIELD #1,2 AS NUMBER$,15 AS AUTHOR$,30 AS BOOK$,1 AS CODE$, 22 AS R ADER$,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" Команды LSET и RSET можно использовать не только при работе с файлами. П р и м е р 3. 10 L$=SPACE$(20):Z$="Волк" ───────────── 20 RSET L$=Z$:PRINT L$ IX.2.5. Ф у н к ц и и MKI$(), MKS$(), MKD$(), CVI(), CVS(), CVD() Вам, конечно, известно, что буферные переменные являются строковыми. Пусть γ- буферная переменная и ей командой FIELD в FCB отведено поле дли- ной m байтов. Если требуется "упаковать" в γ числовое значение,то поль- зуются функциями: ┌────────────────────────────────────────────────────────────┐ α) │ MKI$(L) , │ │ где: MKI("MaKe Integer"-"преобразовать целое значение") │ │ - служебное слово; │ │ L - арифметическое выражение целого типа; │ │ m=2 │; └────────────────────────────────────────────────────────────┘ ┌────────────────────────────────────────────────────────────┐ β) │ MKS$(L) , │ │ где: MKS("MaKe Single"-"преобразовать значение одинарной │ │ точности") - служебное слово; │ │ L - арифметическое выражение одинарной точности; │ │ m=4 │; └────────────────────────────────────────────────────────────┘ ┌────────────────────────────────────────────────────────────┐ γ) │ MKD$(L) , │ │ где: MKD ("MaKe Double"-"преобразовать значение двойной │ │ точности") - служебное слово; │ │ L - арифметическое выражение двойной точности; │ │ m=8 │. └────────────────────────────────────────────────────────────┘ Каждая из этих функций преобразует значение арифметического выражения L к строковому типу. После этого операторами LSET или RSET эти значения можно разместить в γ и соответствующем поле буфера. Обращаем Ваше внимание на тот факт,что функции MKI$(), MKS$() и MKD$() не переводят числовые величины в эквивалентные им знаки кода ASCII, как это делается при использовании других функций. Они просто "упаковывают" соответствующие значения в два,четыре или восемь знаков по той же схеме, которая реализуется в компьютере для представления числовых величин в оперативной памяти. Именно поэтому с помощью оператора PRINT невозможно выдать на печать или экран дисплея результаты работы функций MKI$(), MKS$() и MKD$() ! П р и м е р 1. ────────────── α) функция MKI$(17217) возвращает строку "AC". Рассмотрим, как это по- лучается: 17217=&B0100001101000001=&H4341=&H43·256+&H41=67·256+65 └──────┘└──────┘ ▲ ▲ C A │ └─ Код символа "A" └──────── Код символа "C" β) MKS$(4.14141) возвращает строку "AAAA" П р и м е р 2. A$=MKI$(&HE276):PRINT HEX$(ASC(MID$(A$,1,1)));" "; ────────────── HEX$(ASC(MID$(A$,2,1))) 76 E2 Ok П р и м е р 3. 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 Функции MKI$(),MKS() и MKD() выполняют обратное преобразование по отно- шению к функциям CVI(), CVS() и CVD(), к рассмотрению которых мы сейчас приступаем. Пусть в буфер с дискеты считана запись,и в некотором ее поле,определен- ном по команде FIELD элементом m AS γ "упаковано" числовое значение. "Распаковка" его, или выборка из γ этого значения, реализуется одной из следующих функций: ┌────────────────────────────────────────────────────────────┐ α) │ CVI(γ) , │ │где: CVI("ConVert to Integer"-"преобразовать к целому")- │ │ служебное слово; │ │ γ - имя буферной переменной; │ │ m=2 │; └────────────────────────────────────────────────────────────┘ ┌────────────────────────────────────────────────────────────┐ β) │ CVS(γ) , │ │где: CVS("ConVert to Single"-"преобразовать к значению оди-│ │ нарной точности") - служебное слово; │ │ γ - имя буферной переменной; │ │ m=4 │; └────────────────────────────────────────────────────────────┘ ┌────────────────────────────────────────────────────────────┐ γ) │ CVD(γ) , │ │где: CVD("ConVert to Double"- "преобразовать к значению │ │ двойной точности") - служебное слово; │ │ γ - имя буферной переменной; │ │ m=8 │. └────────────────────────────────────────────────────────────┘ Эти функции преобразуют строки символов в числа. Аргумент состоит из 2, 4 или 8 байтов и преобразуется в целое число, либо число с одинарной или двойной точностью в зависимости от вида используемой функции (CVI, CVS или CVD). П р и м е р 4. ────────────── α) print CVI("AC") print MKI$(17217) 17217 ,так как AC Ok Ok β) print CVS("GWYF") print MKS$(5759460) 5759460 ,так как GWYF Ok Ok Посмотрите на схему... "G" "W" "Y" "F" 0100 0111 0101 0111 0101 1001 0100 0110 ▲───▲──── 5 7 5 9 4 6 │ │ │ Порядок числа = &B1000111-&B1000000 = &B111 = 7 Знак числа Сравните эти результаты с представлением чисел в памяти компьютера (см. далее главу X). П р и м е р 5. ────────────── 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 IX.2.6. О п е р а т о р ы PUT и GET Для пересылки ("сброса") сформированной в оперативной памяти записи на дискету используется оператор ┌────────────────┐ │ PUT [#]n[,P] │ , └────────────────┘ где: 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, в чем Вы можете убедиться самостоятельно. П р и м е р 1. 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 П р и м е р 2. 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 FOP 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 Пусть открыт некоторый файл данных, связанный с буфером FCBn. Полезную информацию о файле можно извлечь с помощью функций LOF и LOC. ┌──────────────┐ Функция │ LOF(n) │ , └──────────────┘ где: LOF ("Length Of File"-"длина файла") - служебное слово; n - арифметическое выражение, целая часть значения которого опреде- ляет номер контрольного буфера файла, возвращает размер файла, связанного с FCBn, в байтах. ┌──────────────┐ Функция │ LOC(n) │ , └──────────────┘ где: LOC ("LOCation"-"определение позиции")- служебное слово; n - арифметическое выражение, целая часть значения которого являет- ся номером файла, возвращает номер т е к у щ е й записи файла (номер записи, использован- ный в последнем выполненном операторе PUT или GET). Для считывания записей файла с дискеты в оперативную память использует- ся оператор ┌─────────────────┐ │ GET [#]n[,P] │ , └─────────────────┘ где: GET ("to get"-"получать") - служебное слово; n, P - арифметические выражения, целые части значений которых задают соответственно номер контрольного буфера файла и номер записи. До выполнения оператора GET необходимо: α) объявить контрольный буфер файла FCBn (оператором MAXFILES=); β) открыть некоторый файл данных В,связанный с FCBn (оператором OPEN); γ) задать формат его записей (оператором FIELD). После всей этой процедуры по оператору GET с диска в буфер # n будет считана запись с номером Р. Фактически будут сформированы значения всех строковых переменных буфера (числовые значения буферных переменных надо "распаковать" с помощью функций CVI, CVS и CVD). Например, оператор GET #1,3 выполняет передачу записи с номером 3 из файла #1 в буфер полей. Если в записи оператора параметр Р отсутствует, то берется текущее зна- чение этого параметра, увеличенное на единицу (как и в операторе PUT). П р и м е р 3. 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 П р и м е р 4. ────────────── 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 П р и м е р 5. ────────────── 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$ П р и м е р 6. ────────────── 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$ Отметим ключевой момент при работе с файлами п р я м о г о доступа: отслеживание "невидимых" указателей. Их два: для дискеты и для буфера. Первый указатель содержит ссылку на текущую запись и задается номером в операторах PUT или GET. Буферный указатель ссылается на элемент данных - переменную, которая в этот момент пишется или читается. Он задается длиной полей в операторе FIELD. Ниже приведены д в е с х е м ы, дающие наглядное представление о по- следовательности операций, которые должны быть выполнены при перемещениях з а п и с е й файлов прямого доступа из оперативной памяти на дискету и в обратном направлении. 1. Общая схема формирования н о в ы х записей уже существующего или вновь создаваемого файла F. ┌────────────────────────────────────────────────────────────────────┐ │ А. В оперативной памяти резервируется буфер (оператором MAXFILES=)│ │ B. О т к р ы в а е т с я файл F (оператором OPEN) │ │ C. Производится распределение полей буфера файла под │ │ значения переменных (оператором FIELD) │ │ D. В буфере формируется запись (при помощи операторов │ │ SET, RSET и функций MKI$(), MKS$(), MKD$() │ │ E. Производится "сброс" записи из буфера на дискету с │ │ присваиванием ей некоторого номера (оператором PUT) │ │ F. Файл F з а к р ы в а е т с я (оператором CLOSE) │ └────────────────────────────────────────────────────────────────────┘ П р и м е р 7. Запись слова в файл прямого доступа. ────────────── 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 2. Общая схема с ч и т ы в а н и я записей из уже существующего файла. ┌────────────────────────────────────────────────────────────────────┐ │ А. В оперативной памяти резервируется буфер (оператором MAXFILES=)│ │ B. О т к р ы в а е т с я файл F (оператором OPEN) │ │ C. Производится распределение полей буфера файла под значения │ │ переменных (оператором FIELD) │ │ D. Производится считывание с диска в буфер оперативной памяти │ │ записи с конкретным номером (оператором GET) │ │ E. По записи из буфера в соответствии с распределением │ │ его поля формируются значения требуемых переменных │ │ (при помощи функций CVI(),CVS(),CVD()). После перенесения │ │ записи в буфер Вы можете манипулировать данными, полученны- │ │ ми из файла, так же, как любыми другими переменными │ │ ┌────────────────────────────────────────────────────────────┐│ │ │Пункты D и E повторяются столько раз, сколько это требуется ││ │ └────────────────────────────────────────────────────────────┘│ │ F. Файл F з а к р ы в а е т с я (оператором CLOSE) │ └────────────────────────────────────────────────────────────────────┘ П р и м е р 8. Чтение слова из файла прямого доступа. ────────────── 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 В заключении этого пункта приведем примеры, иллюстрирующие действие изученных Вами операторов и функций при работе с дисковыми файлами данных прямого доступа. П р и м е р 9. ────────────── 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:CLOSE #1 П р и м е р 10. Дана таблица: ─────────────── ┌──────────────┬─────────┬─────────┐ │ Ф.И. ученика │ Т е м а │ Б а л л │ ├──────────────┼─────────┼─────────┤ │ Фомина Н. │ Графика │ 5 │ │ │ Массивы │ 5 │ ├──────────────┼─────────┼─────────┤ │ Бобкова Н. │ Графика │ 4 │ │ │ Массивы │ 3 │ Заполнить два файла: ├──────────────┴─────────┴─────────┤ 1) список учеников,у которых сре- │ ··· │ дний балл по двум темам ≥ 4 ; ├──────────────┬─────────┬─────────┤ 2) список учеников,у которых хо- │ Герасимова Е.│ Графика │ 5 │ тя бы по одной теме балл 4 или 5. │ │ Массивы │ 3 │ └──────────────┴─────────┴─────────┘ 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 'Вывод на экран П р и м е р 11. ─────────────── 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 IX.3. Ф а й л ы д а н н ы х п о с л е д о в а т е л ь н о г о д о с т у п а При использовании дискеты достаточно указать имя файла,чтобы компьютер начал поиск с использованием каталога. Все участки дискеты в равной степе- ни доступны для записи и чтения, т.е. для обращения к любому участку тре- буется примерно одинаковое время. Напомним Вам, что ┌─────────────────────────────────────────────────────────────────────┐ │ файл, в котором информация может быть найдена без полного просмотра │ │ носителя, мы назвали файлом с п р я м ы м доступом │. └─────────────────────────────────────────────────────────────────────┘ ┌────────────────────────────────────────────────────────────────────┐ │ Файл будем называть файлом с п о с л е д о в а т е л ь н ы м │ │ д о с т у п о м , если компьютер должен "просматривать" его │ │ с самого начала до момента нахождения нужной части. │ └────────────────────────────────────────────────────────────────────┘ Поиск файла на кассетной ленте называется п о с л е д о в а т е л ь- н ы м, потому что компьютер ищет требуемый файл, последовательно перематы- вая магнитную ленту. Любой файл можно организовать так, чтобы можно было использовать либо последовательный, либо прямой доступ, но не оба способа одновременно. Каж- дый способ имеет свои "за" и "против".Последовательный способ намного про- ще для программирования и при его реализации требуется меньше дисковой па- мяти, но может понадобиться больше времени для поиска информации, находя- щейся "в конце" длинного файла. Кроме того, обновление существующих запи- сей в файлах с последовательным доступом трудноосуществимо, а иногда и просто невозможно. Файлы с прямым доступом требуют более сложного программирования и зани- мают обычно больше места на дискете, но очень легко поддаются обновлению, и поиск нужной информации осуществляется с одинаковой скоростью. ┌──────────────────────────────────────────────────────────────────────┐ │ Если при каждом обращении к файлу Вы собираетесь использовать почти │ │ все данные, а менять их содержимое часто не предполагается, то выби- │ │ райте метод п о с л е д о в а т е л ь н о г о доступа. Его приме- │ │ нение будет и более оптимальным и облегчит Вам программирование. │ └──────────────────────────────────────────────────────────────────────┘ Файлы данных последовательного доступа состоят из отдельных групп зна- чений, называемых л о г и ч е с к и м и строками (или просто с т р о - к а м и). Логические строки не имеют номеров и их можно считывать с дискеты или магнитной ленты в оперативную память или записывать из памяти на дискету или магнитную ленту лишь последовательно друг за другом, причем запись производится от начала или конца файла, а чтение - только от его начала. ┌────────────────────────────────────────────────────────────────────┐ │ Каждая логическая строка имеет специальную к о н ц е в у ю метку,│ │ а весь файл имеет еще и метку EOF ("End Of File"-"конец файла"). │ └────────────────────────────────────────────────────────────────────┘ Кроме того, любой конкретный файл открывается или только для чтения, или только для записи, но не для одновременного выполнения этих операций. Для работы с файлами данных п о с л е д о в а т е л ь н о г о доступа в MSX-Disk BASIC предусмотрен ряд операторов и функций. IX.3.1. О п е р а т о р ы MAXFILES= , OPEN и CLOSE Перемещение логических строк последовательных файлов из оперативной па- мяти на дискету и в обратном направлении производится через к о н т р о- л ь н ы е б у ф е р ы ф а й л о в . Последние объявляются оператором MAXFILES=. Максимальное количество файлов, которые могут быть открыты од- новременно, устанавливается оператором ┌────────────────────┐ │ MAXFILES=A │ , └────────────────────┘ где: MAX, FILES - служебные слова; A - арифметическое выражение, целая часть значения которого принад- лежит отрезку [0,15]. При включении компьютера значение параметра A равнo 1.Таким образом,ес- ли Вы хотите открыть т о л ь к о о д и н файл,то использование операто- ра MAXFILES необязательно. ┌──────────────────────────────────────────────────────────────────────┐ │ Файл #0 всегда открыт. MSX-Disk BASIC использует контрольный буфер │ │ этого файла для "своих нужд" (он используется при выполнении │ │ операторов LOAD, SAVE, KILL, RUN, MERGE) │ └──────────────────────────────────────────────────────────────────────┘ При работе с последовательными файлами буфера используются самым прос- тым способом: пересылаемые в файл данные накапливаются в буфере файла, а по заполнении буфера его содержимое сразу целиком переписывается в диско- вый файл;при этом буфер файла очищается для следующей порции выходных дан- ных. При чтении файла соответствующие данные поступают из того же самого буфера, а не считываются непосредственно с поверхности дискеты.Как только все необходимые данные считаны из буфера, средства MSX-BASIC обеспечивают повторное его заполнение информацией из дискового файла. Учтите,что при использовании оператора MAXFILES= автоматически выполня- ется оператор CLEAR, но если Вы используете в программе оба оператора, то располагайте оператор MAXFILES= вслед за оператором CLEAR. Вам, конечно же, ясно, что перед использованием файла Вы должны объя- вить его о т к р ы т ы м . Открытие файла осуществляется оператором OPEN, в котором задается: α) имя устройства (A:,B:,MEM:,CAS:,CRT:,GRP:,LPT:,COM:); β) имя файла; γ) направление потока данных; δ) номер, присвоенный файлу для передачи данных. Синтаксис оператора OPEN: ┌───────────────────────────────────┐ │ { INPUT } │ │ OPEN B FOR { OUTPUT } AS[#]n │ , │ { APPEND } │ └───────────────────────────────────┘ где: OPEN("открыть"), FOR("для"), INPUT("ввод"), OUTPUT("вывод"), APPEND ("присоединение") - служебные слова; В - строковое выражение, значение которого задает имя устройства и имя файла. ┌──────────────────────────────────────────────────────────────────────┐ │ Сейчас мы познакомим Вас с именами у с т р о й с т в: │ │ α) устройство CRT: отвечает за вывод информации на т е к с т о - │ │ в ы й экран ("CaRet"-"символ"); │ │ β) устройство GRP: отвечает за вывод информации на экран в г р а-│ │ ф и ч е с к и х режимах ("GRaPhics"-"графика"); │ │ γ) устройство LPT: отвечает за вывод информации на п р и н т е р │ │ ("Line PrinT"-"печать строки"); │ │ δ) устройство COM: (только для компьютеров MSX-1) отвечает за дви-│ │ жение информации по л о к а л ь н о й сети ("COMmunication"- "пе-│ │ редача данных"); │ │ Φ) устройство MEM: (только для 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: │ └──────────────────────────────────────────────────────────────────────┘ ┌───────────────────────────┐ ┌───────────────────────┐ │ К о н т р о л ь н ы й ◀───INPUT──│ │ │ б у ф е р │──OUTPUT──▶ Д и с к е т а │ │ ф а й л а │──APPEND──▶ │ └───────────────────────────┘ └───────────────────────┘ Оператор OPEN с параметром FOR OUTPUT создает новый дисковый файл с за- данным именем. Если файл с таким именем уже есть,то он автоматически уни- чтожается и создается новый файл с тем же именем. Оператор OPEN...FOR APPEND обеспечивает поиск названного файла среди уже существующих, с тем чтобы добавить новые записи в его конец, но если требуемого файла найти не удалось, то автоматически создается новый файл с заданным именем. Модификация оператора с параметром FOR INPUT реализует поиск данных с конкретным именем, отсутствие которого означает ошибку. П р и м е р ы: ───────────── α) OPEN"CAS:ADDRESS" FOR INPUT AS #1 Устройство: CAS: Файл: ADDRESS Направление: INPUT (файл, сохраненный на ленте, нужно ввести) Номер файла: 1 β) OPEN"ADDRESS" FOR OUTPUT AS #1 Устройство: A: (по умолчанию в MSX-Disk BASIC) Файл: ADDRESS Направление: OUTPUT (файл должен быть создан на дискете) Номер файла: 1 γ) OPEN"B:ADDRESS" FOR APPEND AS #2 Устройство: B: Файл: ADDRESS Направление: APPEND (добавление к уже существующему файлу) Номер файла: 2 Можно открыть файл с последовательным доступом в режиме записи, исполь- зуя один номер файла, и в режиме чтения, используя другой. Однако каждо- му номеру файла будет при этом соответствовать с в о й б у ф е р, никак не связанный с другими. Если же Вы используете только один буфер, то для изменения режима до- ступа к файлу последний необходимо закрыть, а затем вновь открыть. Этот прием особенно удобен, когда Вы хотите использовать в программе в любой момент только один открытый файл (MAXFILES=1). ┌──────────────────────────────────────────────────────────────────────┐ │ Однажды открытый, но не закрытый файл не может быть открыт повторно.│ └──────────────────────────────────────────────────────────────────────┘ В противном случае компьютер сообщает: "File already open". З а к р ы т и е файла позволяет Вам использовать буфер с тем же номе- ром для открытия другого файла. Оператор, закрывающий файлы, выглядит так: ┌───────────────────────────────────┐ │ CLOSE [[#]N1,[#]N2,...,[#]Nk] │ , └───────────────────────────────────┘ где: 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() Да,- повторял он себе,- если бы на борту "Пи- лигрима" я знал все, что должен знать настоя- щий моряк, сколько несчастий можно было бы избежать! Ж.Верн. Дети капитана Гранта Для формирования строк файла с последовательным доступом используются операторы PRINT# и PRINT#USING. Оператор PRINT# записывается в таком виде: ┌────────────────────────┐ │ {└─┘} │ │ PRINT #n,S { ; } │ , │ { , } │ └────────────────────────┘ где: PRINT ("печатать", "вывести") - служебное слово; n - арифметическое выражение, целая часть значения которого опреде- ляет номер контрольного буфера файла; S - список арифметических и (или) строковых выражений: γ1,γ2,...,γk ; └─┘ - обозначение символа пробел (" "). При выполнении оператора PRINT# значение выражения γi (i=1,2,...,k) по- следовательно байт за байтом выводится в буфер почти так же, как это дела- ется командой PRINT . Разница состоит лишь в трактовке зонного формата. ┌───────────────────────────────────────────────────────────────────────┐ │ Если между двумя выражениями в списке S оператора PRINT# раздели- │ │ телем является з а п я т а я ,то при выводе в буфер соответствующих │ │ значений между ними помещается четырнадцать дополнительных пробелов. │ │ Если последним символом в операторе PRINT# является п р о б е л, │ │ то выполнение оператора PRINT# приводит к формированию полной строки, │ │ но вместе с м е т к о й ее окончания. Иначе создается лишь часть │ │ строки, а завершается ее формирование или последующими операторами │ │ PRINT# , или закрытием файла. │ └───────────────────────────────────────────────────────────────────────┘ Длина строки вместе с концевой меткой не может превысить 256 байтов, а данные выводятся на диск в формате ASCII и только тогда, когда заполняет- ся буфер или закрывается файл. Для экономного размещения данных на диске и избежания ошибок при их считывании целесообразно список S в операторе PRINT# записывать в виде: γ1;",";γ2;","; ...;",";γк{└─┘} { ; } В этом случае значения в создаваемой строке располагаются в п л о т - н о м формате и отделяются друг от друга запятыми. Будем считать, что информация в одном операторе PRINT# составляет от- дельную логическую строку. Строка разбивается на п о л я . Каждому полю логической строки соответствует переменная из списка S. Так логическая строка, состоящая из трех полей - фасон одежды S$, цвет одежды C$, цена одежды P - будет выведена в файл оператором PRINT #1,S$;",";C$;",";P ▲ ▲ ▲ │ │ │ Переменные, определяющие поля данной логической строки Если значение какого-либо строкового выражения γi содержит символы "," и (или) ";", то в качестве разделителей можно использовать символ ";", за- даваемый строковой функцией CHR$(34): CHR$(34) γs CHR$(34) П р и м е р 1 [7]. Запись данных в файл последовательного доступа. ───────────────── 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 Если файл с именем "GAMES" уже существовал, то данная программа сотрет его старое содержимое и будет писать туда заново. Оператор PRINT# , не оканчивающийся символом "," или ";" автоматически порождает печать символа ┌─────────────────────────────────┐ │ CHR$(13) (код клавиши "RETURN") │ . └─────────────────────────────────┘ Этот символ попадает в буфер и в конце концов в файл, где он служит разде- лителем между текущей записью и записью, следующей за ней. П р и м е р 2 [5]. Открывается новый или ранее созданный файл "Щука" ───────────────── для вывода в него строк от начала. Программная строка 50 позволяет сформировать в буфере одну строку. 20 OPEN "Щука" FOR OUTPUT AS#1 30 A=5:B$="трава":C=83.157 50 PRINT #1,A;",";B$;",";C 60 CLOSE #1 П р и м е р 3 [5]. Открывается ранее созданный файл "Шука" для вывода ───────────────── в него строк от конца. Затем программная строка 50 формирует очередные строки файла.По мере заполнения буфера данные выводят- ся на дискету,а за последней строкой ставится метка окончания файла (EOF). 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 П р и м е р 4 [5]. Открывается новый или ранее созданный файл "Ка- ───────────────── рась" для вывода в него строк от начала и далее. Двумя командами 50 и 60 формируется строка. 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 П р и м е р 5 [5]. В файл "Карп" от его начала с клавиатуры вводит- ───────────────── ся S элементов числового массива. 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 П р и м е р 6 [5]. При формировании строки в качестве разделителей ис- ───────────────── пользуется символ ", задаваемый кодом CHR$(34). 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 Оператор PRINT#,USING записывается в таком виде: ┌─────────────────────────┐ │ PRINT #n,USING T,S │ , └─────────────────────────┘ где: PRINT, USING - служебные слова; T - строковое выражение, значение которого определяет формат вывода; n - арифметическое выражение, целая часть значения которого определя- ет номер контрольного буфера файла; S - список арифметических и (или) строковых выражений: γ1, γ2,..., γk. При выполнении данного оператора значения выражений γi (i=1,2,...,k) выводятся в соответствии с форматом T в буфер точно так же, как это "дела- ет" "обычный" оператор PRINT USING . П р и м е р 7. ────────────── 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 Однако следует весьма осторожно употреблять префиксы, обозначающие де- нежные единицы ("$$","**" и "**$"), так как они вызывают форматирование числовых величин как нечисловых. По этой причине числовые величины, снаб- женные в дисковом файле такими префиксами, не могут быть считаны оттуда в их исходном виде. П р и м е р 8. ────────────── 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 Пусть открыт файл B , связанный с буфером FCBn. Функция ┌───────────────┐ │ LOF(n) │ , └───────────────┘ где: LOF("Length Of File"-"размер файла") - служебное слово; n - арифметическое выражение, целая часть значения которого принад- лежит отрезку [0,15] и определяет FCB, соответствующий файлу B, возвращает размер файла B в байтах. ┌───────────────┐ Функция │ LOC(n) │ , └───────────────┘ где: LOC ("LOCation"-"определение позиции") - служебное слово; n - арифметическое выражение, целая часть значения которого принад- лежит отрезку [0,15] и определяет FCB, соответствующий файлу B, для файлов последовательного доступа возвращает текущее количество байтов информации, считанных в буфер или записанных на дискету. IX.3.3. О п е р а т о р ы INPUT, LINE INPUT #n . Ф у н к ц и и INPUT$ и EOF Для чтения строк файла последовательного доступа с дискеты в оператив- ную память используются операторы INPUT#, LINE INPUT# и функции INPUT$ и EOF. Оператор ┌──────────────────────┐ │ LINE INPUT #n,γ │ , └──────────────────────┘ где: LINE, INPUT - служебные слова; n - арифметическое выражение, целая часть значения которого опреде- ляет номер контрольного буфера файла; γ - строковая переменная, позволяет считать очередную строку файла β, связанного с буфером n, и при- своить результат переменной γ. Оператор LINEINPUT# , считывающий одиночное строковое значение, позво- ляет решить "проблему запятой". П р и м е р 1. ────────────── 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 П р и м е р 2. ────────────── 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 Оператор INPUT# записывается в виде ┌─────────────────┐ │ INPUT #n,S │ , └─────────────────┘ где: INPUT - служебное слово; n - арифметическое выражение, целая часть значения которого определя- ет номер контрольного буфера файла; S - список переменных. Опишем, как происходит выполнение этого оператора. Если очередная считываемая строка файла состоит из значений: α1, α2,..., αk, то в соответствующей команде INPUT# список S должен иметь такой вид: β1, β2,..., βk, а каждая переменная βi обязана быть того же типа,что и значение αi.В этом случае выполнение оператора приводит к присваиваниям переменным βi значе- ний αi. П р и м е р 3. Чтение из файла последовательного доступа. ────────────── 10 OPEN "GAMES" FOR INPUT AS #2 20 FOR X=1 TO 5:INPUT #2,G$:PRINT G$:NEXT X:CLOSE #2 run Футбол Гольф Баскетбол Хоккей Регби Ok П р и м е р 4. ────────────── 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 П р и м е р 5. ────────────── 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 При выполнении оператора PRINT# (строка 20) в файл записываются три различных значения, но поскольку в операторе они разделяются символами ";", в файл они будут заноситься без разделителей. Когда оператор INPUT# реализует считывание этих значений (строка 50), они все "сливаются" в од- но. Таким образом, в файле не будет существовать ни второго, ни третьего значений, поэтому при попытке чтения программой какой-либо информации за последним значением в файле фиксируется ошибка "Считывание за пределами последнего значения". Разделителем для строковых данных может быть запятая или символ "Воз- врат каретки". Те же самые знаки или пробелы служат для разграничения чис- ловых величин. Существует несколько способов гарантированной расстановки разделителей между отдельными значениями. Один из самых простых состоит в том, чтобы присвоить значение "," строковой переменной и записывать ее по- сле каждого значения в операторе PRINT# . П р и м е р 6. ────────────── 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 Отметим, что строковая величина в дисковом файле, могущая содержать за- пятую, должна быть записана в кавычках; оператор INPUT# обеспечивает устранение этих кавычек при считывании. П р и м е р 7. ────────────── 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 П р и м е р 8[7]. О б н о в л е н и е файла последовательного доступа. ───────────────── 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" 'Переименование "нового" файла П р и м е р 9. ────────────── 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 Заметим, что строка 100 в этом примере могла быть заменена на один из фрагментов: а) 100 INPUT #4,M$ b) 100 INPUT #4,M$ 101 INPUT #4,A,B 101 INPUT #4,A 102 INPUT #4,B Для чтения очередного фиксированного количества символов из файла без учета его разбиения на строки используется функция ┌─────────────────────┐ │ INPUT$(m[,[#]n]) │ , └─────────────────────┘ где: INPUT$ - служебное слово; m - арифметическое выражение, целая часть значения которого должна принадлежать отрезку [1,255]; n - номер контрольного буфера файла. В любой момент работы с файлом функция INPUT$ "читает" INT(m) его оче- редных символов. Иными словами, последовательность этих символов становит- ся значением функции INPUT$(). При этом метки окончания строк воспринима- ются так же, как любые другие символы. Функция INPUT$ возвращает строку, содержащую заданное количество симво- лов, прочитанных из файла. ┌─────────────────────────────────────────────────────────────────┐ │ Все символы, включая разделители, передаются в программу, за │ │ исключением специального символа с кодом ASCII &H1A , который │ │ воспринимается как признак конца файла и "прекращает выполне- │ │ ние" функции. │ └─────────────────────────────────────────────────────────────────┘ Функция INPUT$ предоставляет возможность последовательно выбирать сим- волы из файла независимо от разделителей строк! Для полного уяснения семантики функции INPUT$ рекомендуется "прогнать" следующий пример при различных значениях параметров S и X. П р и м е р 10[5]. ────────────────── 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 Заметим, что "длину" файла не всегда можно определить заранее: предста- вьте себе файл адресов, который все время приходится открывать в режиме добавления данных (FOR APPEND). Функция EOF позволяет Вам решить эту проб- лему: специальный символ с кодом &h1А добавляется к концу файла, когда этот файл закрывается. Этот символ помечает к о н е ц файла. Функция EOF , синтаксис которой ┌──────────────┐ │ EOF(n) │ , └──────────────┘ где: EOF ("End Of File" - "конец файла") - служебное слово; n - арифметическое выражение, целая часть значения которого определя- ет номер файла, сравнивает код очередного символа с кодом &h1А и возвращает: -1 ("true"), если найден код конца файла, и 0 ("false") в противном случае. П р и м е р 11. Продемонстрируем способ использования функции EOF(). ─────────────── 10 OPEN "TESTF" FOR INPUT AS #1 20 IF EOF(1) THEN 60 30 INPUT #1,A:PRINT A:GOTO 20 60 CLOSE #1 Ниже приведены 3 схемы, определяющие последовательность операций, кото- рые должны быть выполнены при перемещениях строк файлов п о с л е д о в а- т е л ь н о г о д о с т у п а из оперативной памяти на дискету и в об- ратном направлении. ┌───────────────────────────────────────────────────────────────────────┐ │ 1. Общая схема формирования строк на диске от н а ч а л а файла В: │ │ А. В оперативной памяти резервируется буфер (оператором MAXFILES=).│ │ B. Открывается новый или уже существующий файл В (оператором OPEN │ │ с параметром OUTPUT). │ │ C. Формируется требуемое количество строк файла(операторами PRINT# │ │ или PRINT#,USING). На дискету из буфера они сбрасываются автома-│ │ тически. │ │ D. Файл В закрывается. │ └───────────────────────────────────────────────────────────────────────┘ П р и м е р 12 [7]. ─────────────────── 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 Отдельные сегменты программных файлов - это специфические файлы данных последовательного доступа. Поэтому программы или их фрагменты можно загру- жать в память как данные. Ограничимся здесь лишь двумя примерами. П р и м е р 13. Выполнение этой программы приводит к считыванию и вы- ─────────────── воду на экран всех строк программы "Симпсон". 10 'Чтение программного файла 20 OPEN "Симпсон" FOR INPUT AS#1 30 LINE INPUT #1,R$:PRINT R$ 50 IF NOT EOF(1) THEN 30 60 CLOSE #1 П р и м е р 14. Выполнение программы дает возможность "просмотреть" в ─────────────── той же самой программе "Симпсон" строки с номерами от 30 и до 70. 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 ┌───────────────────────────────────────────────────────────────────────┐ │ 2. Общая схема пополнения файла В строками с его к о н ц а: │ │ А. В оперативной памяти резервируется буфер (оператором MAXFILES=).│ │ B. Открывается уже открытый файл В (оператором OPEN с параметром │ │ APPEND). │ │ C. Формируется требуемое количество строк файла(операторами PRINT# │ │ или PRINT#,USING). На дискету из буфера они сбрасываются автома-│ │ тически. │ │ D. Файл В закрывается. │ └───────────────────────────────────────────────────────────────────────┘ П р и м е р 15 [7]. Добавление в файл спортивной информации названия ──────────────────── двух новых видов спорта. 10 OPEN "GAMES" FOR APPEND AS#1 20 PRINT #1,"Пинг-понг":PRINT #1,"Теннис":CLOSE #1 ┌───────────────────────────────────────────────────────────────────────┐ │ 3. Общая схема с ч и т ы в а н и я строк с диска от начала файла В │ │ А. В оперативной памяти резервируется буфер (оператором MAXFILES) │ │ В. Открывается уже существующий файл В (оператором OPEN с парамет- │ │ ром INPUT) │ │ C. Считывается требуемое количество строк файла(операторами INPUT$ │ │ или LINEINPUT$, или INPUT$) │ │ D. Файл В закрывается │ └───────────────────────────────────────────────────────────────────────┘ П р и м е р 16 [7]. ─────────────────── 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 IX.3.4. П р и м е р ы 1. Гидрометцентр ведет статистику выпадения снега по регионам, для каж- дого из которых заведен файл последовательного доступа.Во всех файлах име- ется по три элемента данных: имя метеоролога, название региона, количест- во выпавшего за зиму снега в мм. α) Напишите программу ввода данных; заполните файлы для трех регионов. β) Просмотрите все три файла и подсчитайте средний уровень снежных осадков по трем регионам. Результат выведите на экран. 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$:INPU T "количество выпавшего за зиму снега в мм";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 2. Хоккейные команды "Черные ястребы" и "Красные крылья" хранят в фай- лах последовательного доступа имена всех своих 12 нападающих, число забро- шенных ими шайб, сделанных голевых передач и заработанное штрафное время. α) Создайте файлы "BLACK" и "RED", содержащие информацию о каждой из двух команд. β) Ваша программа по данным, извлеченным из этих файлов, должна порож- дать новый файл "ALLSTARS", в котором содержались бы имя, команда и сумма очков (голы + передачи) для шести лучших игроков обеих команд. Выведите имена и показатели результативности хоккеистов на экран дисплея. 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)=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 IX.3.5. В ы в о д ф а й л о в д а н н ы х на э к р а н и п р и н т е р Текстовые экраны 0 и 1, графические экраны, а также принтер могут быть объявлены устройствами вывода файлов последовательного доступа. О т к р ы т и е таких файлов осуществляется оператором ┌───────────────────────────────────┐ │ {"CRT:"} │ │ OPEN {"GRP:"} FOR OUTPUT AS[#]n │ , │ {"LPT:"} │ └───────────────────────────────────┘ где: OPEN, FOR OUTPUT, AS - служебные слова; n - арифметическое выражение, целая часть значения которого определя- ет номер контрольного буфера файла; CRT:, GRP:, LPT: - имена устройств. При выполнении оператора OPEN в качестве устройства вывода файлов на- значаются: т е к с т о в ы е экраны (CRT:), г р а ф и ч е с к и е экраны (GRP:), п р и н т е р (LPT:). Вывод строк в любом случае осуществляется операторами PRINT# и PRINT#,USING. Поговорим о выводе п р о г р а м м н ы х файлов на экран и принтер. Используя устройства CRT:, GRP: и LPT:, можно выводить текст программы на экран и принтер. 1. Команда SAVE "LPT:" предназначена для вывода текста программы на п р и н т е р . 2. Команда SAVE "CRT:" позволяет выводить текст программы на т е к с т о в ы й экран. 3. Команда SAVE "GRP:" позволяет выводить текст программы на г р а ф и ч е с к и й экран. Использование "графического" оператора SAVE "GRP:" в текстовом режиме приводит к сообщению об ошибке: "Illegal function call". Вполне естественно,что команды LOAD, RUN и MERGE не могут "работать" с устройствами CRT:, GRP: и LPT: ! П р и м е р ы: ───────────── 1) 10 COLOR 1,11,7:SCREEN 2:OPEN "GRP:" FOR OUTPUT AS#1 30 PSET (69,80):PRINT #1,"Текст на графическом экране SCREEN 2" 50 GOTO 50 2) 10 COLOR 1,11,7:SCREEN 3:OPEN "GRP:" FOR OUTPUT AS#1 30 PSET (50,80):PRINT #1,"Текст на графическом экране SCREEN 3" 50 GOTO 50 3) Программа "777", записанная на диске в формате ASCII, выводится на графический экран: 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 4) Файл данных последовательного доступа,записанный на дискете под име- нем "КАРП", выводится на принтер. 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 П р и м е р 5 [76]. Простейший г р а ф и ч е с к и й редактор. ────────────────── При формировании изображения Вам могут понадобить- ся такие команды: L При нажатии этой клавиши определяется начальная точка прямой.При повторном нажатии вычерчивается прямая. P Закрашивается участок экрана. U Отменяется последняя команда. DEL Уничтожается программа, запущенная из памяти, а экран очищается. ESC Генерируется программа. После окончания формирования изображения текст программы на языке MSX- BASIC можно вызвать на экран, либо записать на ленту или дискету (по ко- манде SAVE.При необходимости программу с ленты или с дискеты можно вновь загрузить (командой LOAD) или "слить" с другой программой, хранящейся в памяти (командой MERGE). Один из спрайтов задействуется как курсор, другой - в качестве марке- ра, отмечающего начало прямой, и еще шесть в качестве "координатных",что- бы отмечать текущие координаты курсора на экране. Когда курсор "касается" одного из "координатных" спрайтов, они пропадают. Это выполняется с испо- льзованием прерывания по ON SPRITE GOSUB. 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,2 09):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 IX.4. И с п о л ь з о в а н и е RAM-д и с к а (т о л ь к о д л я к о м п ь ю т е р о в MSX-2) RAMdisk (псевдодиск) - логическое устройство, обеспечивающее хранение файлов в специально выделенной области оперативной памяти.Исполь- зуется на микроЭВМ и ПЭВМ. Англо-русский словарь по програм- мированию и информатике Свободное пространство памяти, размер которого можно определить при по- мощи функций FRE(0) и FRE(""), автоматически распределяется интерпретато- ром MSX-BASIC. Когда программа слишком длинна или использует слишком мно- го переменных, для временного хранения данных следует использовать либо внешние устройства (магнитные ленты, дискеты),либо дополнительную область памяти MSX-компьютера (так называемый RAM-д и с к). Эта дополнительная область не распределяется а в т о м а т и ч е с к и- т.е. если программа, например, использует слишком много переменных, это еще не значит,что значения этих переменных будут автоматически перенесены в дополнительную область оперативной памяти! Вы сейчас убедитесь в том, что доступ к этой области осуществляется аналогично доступу к д и с к о в о д а м ! ┌──────────────────────────┐ Оператор │ CALL MEMINI [(R)] │ , └──────────────────────────┘ где: CALL ("вызвать"), MEMINI ("MEMory INIcialisation" - "инициализация памяти") - служебные слова; R - арифметическое выражение, целая часть значения которого принима- ет значения от 6655 до M-32769 , где M - максимальный объем RAM , инициализирует RAM-диск и сообщает его текущий свободный объем. Этот опе- ратор должен быть выполнен до первой попытки обращения к RAM-диску. ┌────────────────────────────────────────────────────────┐ │ Помните, что это обращение у н и ч т о ж а е т все │ │ файлы, записанные до этого на RAM-диск. │ └────────────────────────────────────────────────────────┘ Отметим, что для MSX-компьютеров с общим объемом RAM в 128 Кбайтов зна- чение параметра R не должно превышать 98303 байта. Фактический же размер RAM-диска (в байтах) равен значению арифметичес- кого выражения R - 6399 . Если значение параметра R меньше указанного минимального значения, то RAM-диск "отключается" и компьютер выдает сообщение: "No RAM disk" , если же значение параметра R больше максимального значения, то появляется сообщение о неправильном вызове функции "Illegal function call" . Когда параметр R опущен, то его значение по умолчанию устанавливается равным максимальному, т.е. 98303-6399 = 91904 ≈ 92 Кбайта. Параметр R необходим, если Вы хотите использовать дополнительные облас- ти RAM как для временного хранения файлов, так и для других целей. Если же это не так, то используйте команду ┌────────────────────┐ │ CALL MEMINI │ . └────────────────────┘ И м е н а файлов, находящихся на RAM-диске, должны включать: α) имя устройства "МЕМ:", β) имя файла, состоящее не более чем из 8 символов (причем символы "*" и "?" не могут использоваться!), и γ) расширение имени файла,состоящее из точки и не более чем из 3-х сим- волов. Впрочем, расширение имени файла не обязательно; если оно пропущено, то точка также может быть опущена. Например: "МЕМ:PROGRAM1.BAS" "MEM:HRU" Команды для работы с RAM-диском очень похожи на команды FILES, KILL и NAME версии MSX-Disk BASIC. ┌────────────────────┐ 1) Команда │ CALL MFILES │ , └────────────────────┘ где: CALL, MFILES - служебные слова; выводит на экран список файлов, записанных на RAM-диске, и размер оставше- гося свободного пространства. ┌──────────────────────────────────┐ 2) Команда │ CALL MKILL ("И м я ф а й л а") │ , └──────────────────────────────────┘ где: CALL, MKILL - служебные слова; "стирает" файл с указанным именем с RAM-диска. Обратите внимание на то, что параметр "И м я ф а й л а" заключается в круглые скобки! 3) Команда ┌───────────────────────────────────────────────────────────────────────┐ │ CALL MNAME ("Имя с т а р о г о файла" AS "Имя н о в о г о файла") │, └───────────────────────────────────────────────────────────────────────┘ где: CALL, MNAME - служебные слова; параметр "Имя с т а р о г о файла" обязательно должен присутство- вать, параметр "Имя н о в о г о файла" может быть опущен; позволяет изменить имя файла. Перечислим теперь операторы и функции, которые можно использовать для работы с программными файлами и с файлами п о с л е д о в а т е л ь н о - г о доступа: SAVE LOAD MERGE RUN OPEN CLOSE PRINT# PRINT#USING INPUT# INPUT$ LINEINPUT# EOF LOC LOF FPOS ┌───────────────────────────────────────────────────────┐ │ Помните, однако, что имя устройства МЕМ: обязано │ │ присутствовать всякий раз при упоминании имени файла! │ └───────────────────────────────────────────────────────┘ Приведем несколько примеров записи операторов для работы с RAM-диском: MERGE"MEM:файл" OPEN "MEM:файл" FOR INPUT AS#1 SAVE"MEM:файл" OPEN "MEM:файл" FOR OUTPUT AS#6 LOAD"MEM:файл" OPEN "MEM:файл" FOR APPEND AS#15 RUN"MEM:файл" П р и м е р. ─────────── 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 ┌────────────────────────────────────────────────────────────────┐ │ Команда SAVE всегда записывает программу в формате ASCII, │ │ после чего она "готова к употреблению" операторами MERGE и RUN.│ └────────────────────────────────────────────────────────────────┘ Отметим, что на RAM-диске может существовать один файл с п у с т ы м именем. Таким образом, синтаксически допустимы следующие конструкции: SAVE"MEM:" LOAD"MEM:" RUN"MEM:" MERGE"MEM:" OPEN"MEM:" ┌──────────────────────────────┐ Функция │ LOC(Н о м е р ф а й л а) │ └──────────────────────────────┘ возвращает позицию в файле, начиная с номера файла. Например, LOC вовраща- ет 0 сразу после того, как файл открыт для ввода и вывода (OPEN FOR INPUT/ OUTPUT),и возвращает длину файла cразу после того, как файл открыт для до- бавления (OPEN FOR APPEND). ┌────────────────────────────────┐ Функция │ LOF(Н о м е р ф а й л а) │ └────────────────────────────────┘ возвращает объем файла. ┌────────────────────────────────┐ Функция │ FPOS(Н о м е р ф а й л а) │ └────────────────────────────────┘ возвращает оставшийся объем RAM-диска. Все остальные операторы и функции, перечисленные выше,используются ана- логично соответствующим конструкциям,используемым в версии MSX-Disk BASIC. IX.5. Ф а й л ы на м а г н и т н о й л е н т е Вывод программных файлов и файлов данных из оперативной памяти на маг- нитную ленту и обратное считывание с ленты в память реализуется через устройство, называемое м а г н и т о ф о н о м. Для идентификации файлам присваиваются и м е н а , конструируемые из символов алфавита языка. Длина имени не может превосходить 6 символов (операторы SAVE, CSAVE) или 11 (оператор BSAVE). Уникальность имен не обязательна. Работа с магнитофоном может быть организована в рамках любой версии языка MSX-BASIC. Для этих целей предусмотрены следующие команды и функции. 1. SAVE - команда записи в формате ASCII программ из оперативной памя- ти на магнитную ленту. 2. LOAD - команда чтения в оперативную память программ, записанных на магнитной ленте в формате ASCII. 3. MERGE - команда подгрузки в память программ, записанных на ленте в формате ASCII. 4. RUN - команда загрузки в память программ, записанных на ленте в формате ASCII, с автоматическим запуском их на счет. 5. CSAVЕ - команда записи во внутреннем представлении программ из опе- ративной памяти на ленту. 6. CLOAD - команда чтения в оперативную память (или верификации) про- грамм, записанных на ленте во внутреннем представлении. 7. BSAVE - команда записи во внутреннем представлении программных фай- лов или файлов данных из конкретного участка оперативной памяти на ленту. 8. BLOAD - команда считывания в определенную область оперативной памя- ти программных файлов и файлов данных, записанных на ленте во внутреннем представлении. 9. OPEN │ 10. CLOSE │ 11. MAXFILES= │ 12. EOF() │ операторы и функции для работы с файлами 13. PRINT# │ данных последовательного доступа 14. PRINT#USING │ 15. INPUT# │ 16. LINE INPUT# │ 17. INPUT$() │ Приступим к краткому описанию синтаксиса и семантики упомянутых выше средств организации файлов на магнитной ленте и работы с ними. IX.5.1. Р а б о т а с п р о г р а м м н ы м и ф а й л а м и В этом пункте описаны команды SAVE, LOAD, MERGE, RUN. А. Команда ┌─────────────────┐ │ SAVE α [,A] │ , └─────────────────┘ где: SAVE - служебное слово; α - строковое выражение; записывает в формате ASCII на магнитную ленту программу из оперативной па- мяти. Имя программы формируется из первых 6 символов значения строкового вы- ражения α. Оно должно начинаться префиксом "CAS:", который в этом случае рассматривается как и м я у с т р о й с т в а и не учитывается при под- счете длины α, например: SAVE"CAS:СОСНА" , SAVE"CAS:анкета",A . Заметим, что имя программы может быть опущено. Например: SAVE"CAS:" В. Выполнение команды ┌─────────────────┐ │ LOAD α [,R] │ , └─────────────────┘ где: LOAD - служебное слово; α - строковое выражение, значение которого определяет имя файла; наличие параметра R приводит к автоматическому запуску загруженной программы на счет, начинается с закрытия всех файлов и чистки оперативной памяти от программ и данных. Далее программа, записаная на ленте в формате ASCII под именем, равным значению строкового выражения α, считывается в память. Например: LOAD"CAS:труба" , LOAD"CAS:King",R . Поиск конкретной программы на ленте сопровождается индикацией сообще- ний обо всех "попавшихся под руку" при этом файлах с другими именами, за- писанных в формате ASCII. Приведем пример сообщения на экране дисплея при выполнении команды LOAD (учтите, что: "to skip"-"перескочить", "to found" - "находить"): α) Skip:PRIM1 Skip: ◀── встретилась программа без имени Found:PRIM3 β) Found: ◀── найдена и загружается программа без имени. ┌───────────────────────┐ Команда │ LOAD"CAS:" [,R] │ └───────────────────────┘ считывает в память первую встреченную на ленте программу в формате ASCII. ┌───────────────────────┐ C. │ RUN α │ └───────────────────────┘ Эта команда, если в ней указаны имя устройства и имя программы,загружа- ет и запускает на выполнение программу, сохраненную в формате ASCII. Она похожа на команду LOAD (с параметром R) за тем исключением,что она загру- жает программы только в формате ASCII и закрывает все открытые файлы. В обоих случаях перед загрузкой программы автоматически выполняется ко- манда NEW. П р и м е р. Команда RUN"CAS:PROG1" загружает и запускает программу ─────────── с именем "PROG1",сохраненную на магнитной ленте командой SAVE"CAS:PROG1" D. При выполнении команды ┌──────────┐ │ MERGE α │ , └──────────┘ где: MERGE - служебное слово; α - строковое выражение, значение которого определяет имя файла, закрываются файлы и организуется "чистка" оперативной памяти от данных. Затем, программа, записанная на ленте в формате ASCII под именем, рав- ным значению строкового выражения α, "сливается" с программой β, находя- щейся в памяти. При этом,если в α и β совпадают некоторые номера строк,то сохраняются лишь соответствующие строки загружаемой программы α. Например: MERGE"CAS:Мама!" Выдача сообщений на экране при поиске программы α здесь такая же,как и в случае с командой LOAD. ┌───────────────┐ Команда │ MERGE"CAS:" │ └───────────────┘ подгружает в память первую встреченную на ленте в формате ASCII программу. Обратите внимание на тот факт,что программы, вызываемые командой MERGE, имеют более высокий приоритет по сравнению с программами, находящимися в памяти компьютера. Поэтому если в объединяемых программах имеются строки с одинаковыми номерами, то строки программы в памяти компьютера будут за- менены соответствующими строками "добавляемой" программы. А. Команда (оператор) CSAVE "сохраняет"программу, записывая ее на кас- сету магнитной ленты. Формат оператора: ┌───────────────┐ │ CSAVE β;[S] │ , └───────────────┘ где: CSAVE("Casette SAVE"-"запись на кассету") - служебное слово; β - строковое выражение, значение которого определяет имя файла, в имени программы допускается использование любых символов, причем значащи- ми в имени являются только первые шесть символов; S - арифметическое выражение, целая часть значения которого равна 1 или 2 и определяет скорость записи данных (по умолчанию значение парамет- ра S равнo 1): ┌──────────────────────────────┐ │ 1 ──▶ 1200 бод (1200 бит/с) │ │ 2 ──▶ 2400 бод (2400 бит/с) │ └──────────────────────────────┘ Скорость 2400 бод требует использования хорошего магнитофона и высоко- качественной ленты.Скорость работы по умолчанию может быть переопределена в операторе SCREEN (см.раздел V.7.). ┌───────────────────────────────────────────────────────────────────────┐ │ Команда CSAVE "сохраняет" программу во в н у т р е н н е м формате,│ │ т.е. в том виде, в каком она хранится в памяти компьютера. │ └───────────────────────────────────────────────────────────────────────┘ П р и м е р ы: ───────────── α) команда CSAVE"PROG1" сохраняет файл, имя которого "PROG1", во внут- реннем формате со скоростью 1200 бод (или со скоростью, определенной опе- ратором SCREEN); β) команда CSAVE"PROG2",2 сохраняет файл с именем "PROG2" на кассетной ленте во внутреннем формате со скоростью 2400 бод. ┌────────────────┐ B. Команда │ CLOAD β │ , └────────────────┘ где: CLOAD ("Cassette LOAD"-"загрузка с кассеты") - служебное слово; β - строковое выражение, значение которого определяет имя файла, позволяет загружать программу, сохраненную на кассетной ленте во внутрен- нем формате (с помощью команды CSAVE). Загрузка выполняется на той же ско- рости, на которой программа была сохранена. Таким образом, Вам не нужно повторно указывать скорость. Если имя программы не указано в операторе,то будет загружена первая же программа, сохраненная во внутреннем формате. Если Вы указываете имя программы,то следите за правильностью ввода име- ни (т.е.,например, если Вы использовали прописные буквы при написании име- ни, Вы должны ввести имя программы также прописными буквами). ┌───────────────────────────────────────────────────────────────────┐ │ Заметим, что оператор CLOAD автоматически выполняет команду NEW │ │ перед началом загрузки в память найденной программы │ └───────────────────────────────────────────────────────────────────┘ С. Оператор CLOAD? проверяет правильность сохранения программы на кас- сетной ленте.После сохранения программы перемотайте ленту назад и введите команду ┌──────────────┐ │ CLOAD? β │ , └──────────────┘ где: CLOAD?("Casette LOAD verify"-"загрузка с ленты") - служебное слово; β - строковое выражение, значение которого определяет имя файла. Записанная программа, имя которой указано в операторе, сравнивается байт за байтом с текстом программы в памяти компьютера. При обнаружении несов- падения эта процедура прекращается и на экране появляется сообщение об ошибке: "Verify error" ("О ш и б к а в е р и ф и к а ц и и"). Имя программы может быть опущено. В этом случае с содержимым памяти бу- дет сравниваться первая введенная с ленты программа. Если имя программы не совпадает с именем, указанным в операторе, поиск программы с указанным именем будет продолжен. На экране дисплея появится следующее сообщение: Skip:имя программы В нем указано имя найденной "по пути" программы или файла данных. ┌─────────────────────────┐ D. По команде │ BSAVE α,β1,β2[,β3] │ , └─────────────────────────┘ где: BSAVE ("Binary SAVE") - служебное слово; α - строковое выражение; β1,β2,β3 - арифметические выражения, значения которых задают адреса в RAM, содержимое оперативной памяти от β1 и до β2 записывается во внут- реннем представлении на ленту под именем, равным значению строкового выра- жения α. Значение выражения β3 определяет адрес,с которого программа при загрузке ее в память будет запускаться на счет (по умолчанию значение β3 равно значению β1). Если вывод осуществляется не на дисковод А, то следует указать имя устройства. Затем укажите: α) имя файла, β) начальный адрес сохраняемых данных, γ) конечный адрес сохраняемых данных и, возможно, δ) адрес выполнения; если последний пропущен, то адрес, отмечающий на- чало данных, будет автоматически рассматриваться как адрес выполнения при загрузке этих данных (эта часть информации полезна только в том случае,ес- ли сохраняются подпрограммы на машинном языке). П р и м е р ы. 1) BSAVE "CAS:ГОСТ",&HF000,&HF0EE ───────────── 2) BSAVE "CAS:" A,B,C Команда BSAVE позволяет сохранить часть оперативной памяти на ленте или дискете. Это может быть подпрограмма на MSX-BASIC, данные, подпрограм- мы ROM, рабочая область. ┌─────────────────────────────────────────────────────────────────────┐ │ Оператором BSAVE может быть сохранена часть памяти между ячейками │ │ с адресами &H0 и &HFFFF │ └─────────────────────────────────────────────────────────────────────┘ На компьютерах MSX-2 возможна и другая форма записи оператора BSAVE: ┌────────────────────────────────────────┐ │ BSAVE"CAS: и м я ф а й л а",β1,β2,S │. └────────────────────────────────────────┘ Этот оператор сохраняет на кассетной ленте содержимое видеопамяти. ┌────────────────────┐ E. По команде │ BLOAD α,[,R][,β] │ , └────────────────────┘ где: BLOAD ("Binary LOAD") - служебное слово; α - строковое выражение; R - параметр; β - арифметическое выражение;значение параметра β должно быть целым, оно определяет величину смещения адресов β1, β2 и β3 загрузки и запуска (по умолчанию β=0), в оперативную память загружается файл, записанный на ленте во внутреннем представлении под именем, равным значению выражения α.При наличии парамет- ра R прочитанная программа автоматически запускается на счет. П р и м е р ы. 1) BLOAD "CAS:DD" ───────────── 2) BLOAD "CAS:LEN", &H1500 3) BLOAD "CAS:TEST", R 4) BLOAD "CAS:",R 5) 5 'Инициализация компьютера. 10 CALL NETEND 'Для компьютеров серии MSX-2 20 BSAVE"CAS:initio",0,3 30 BLOAD"CAS:initio",R,&HA000 В последнем примере подпрограмма ROM, расположенная между адресами &h0 и &h3, загружается в RAM по адресу &HA000 и запускается на выполнение. Команда BLOAD позволяет загрузить данные, сохраненные командой BSAVE. Должно быть указано имя устройства, если это не дисковод А, и имя файла. Может присутствовать параметр R, если данные относятся к программе на ма- шинном языке. В этом случае программа запустится после загрузки.Данные за- гружаются на то место, которое они занимали перед сохранением,если не ука- зан адрес смещения. В этом случае данное число добавляется к начальному, конечному и адресу смещения, заданным в команде BSAVE. На компьютерах MSX-2 возможна и другая форма записи оператора BLOAD: ┌─────────────────────────────────────────────┐ │ BLOAD"CAS: и м я ф а й л а",S │ └─────────────────────────────────────────────┘ Содержимое файла будет скопировано в видеопамять. Обратите внимание, что BLOAD может использоваться в программе, не вызы- вая выполнения команды NEW или возврата в командный режим. Этот оператор может использоваться также для загрузки частей программы на MSX-BASIC. П р и м е р 1. Приведем программу, которая позволяет указать начальный ───────────── и конечный адреса загрузки двоичного файла. 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 З а м е ч а н и е. Команды BSAVE и BLOAD можно применять и для работы с произвольными дисковыми файлами (устройства A: и B:). П р и м е р 2. Запись компьютерных игр с дискеты на магнитную ленту. ───────────── 1) Загрузите программу с дискеты в оперативную память командой BLOAD "имя файла" 2) Включите Ваш магнитофон на запись, затем выполните команду BSAVE "CAS:имя файла",α,β,γ где: α - ш е с т н а д ц а т е р и ч н ы й начальный адрес; β - ш е с т н а д ц а т е р и ч н ы й конечный адрес; γ - ш е с т н а д ц а т е р и ч н ы й адрес загрузки. Значения α,β,γ Вы можете найти с помощью программы из примера 1. П р и м е р 3. Загрузка компьютерных игр с магнитной ленты в оператив- ───────────── ную память. 1. Включите магнитофон 2. Выполните команду BLOAD "CAS: И м я ф а й л а",R 3. На экране появится надпись: Found: И м я ф а й л а (без расширения) 4. ...И "игрушка" запустится! IX.5.2. Р а б о т а с ф а й л а м и д а н н ы х Команда OPEN для устройства CAS: имеет следующий вид: ┌─────────────────────────────────┐ │ OPEN β FOR {INPUT } AS #n │ │ {OUTPUT} │ . └─────────────────────────────────┘ Здесь β должно начинаться с символов "CAS:" и, кроме того, отсутствует возможность, предоставляемая параметром APPEND для "наращивания" файлов. Все остальное полностью аналогично работе с дисковыми файлами (устройства A:, B: и MEM:). П р и м е р. Строки 10÷30 создают файл данных на магнитной ленте. Для ─────────── его считывания в память требуется запустить этот фрагмент со строки 50. 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 IX.6. Д о п о л н е н и е. Три очень п о л е з н ы х программы: 1. Программа, осуществляющая посекторное копирование диска на кассету. 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 TH EN 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 G OTO 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 2. Программа,осуществляющая посекторное восстановление диска с кассеты. 6 CLS:PRINT:PRINT"<<Посекторное восстановление диска с кассеты>>":PRIN T: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 G OTO 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 3. Программа, позволяющая определить тип файла на кассете. В н и м а н и е! При наборе программы с т р о г о соблюдайте пробелы между символами и нумерацию строк. 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:RESTORE 4: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):I FNOT(("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 !":RETURNEL SE12 14 RESUMENEXT 15 KEYON:POKE&H80CA,58' 16 END