Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

для т. точно

.pdf
Скачиваний:
7
Добавлен:
14.05.2015
Размер:
532.34 Кб
Скачать

-последовательного доступа (чтение и запись данных начинаются всегда от начала файла)

-прямого доступа (чтение и запись данных возможны для любого места) 2 Способы представления (хранения).

Для различия между собой, файлы имеют имена. Имена имеют и ВУ: CON, KBD, CRT, PRN, LPT1,...LPT3, COM1, COM2 (ДОС);

GRP (MSX-basic); SCRN, KYBD (GWbasic)

Стандартными внешними устройствами являются клавиатура и дисплей. Используя при передаче файловой информации вместо имен файлов имена устройств, получают ввод информации с указаных устройств или вывод информации на нестандартные устройства. Поэтому имена устройств нельзя давать файлам.

Полное имя файла состоит из трех частей:

адресная - <имя устройства памяти>:[/<имена подкаталогов через />] именная - <имя файла до 8 знаков> расширение имени файла - <три знака>

При написании, между именем файла и расширением ставится точка.

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

ТЕКСТ - набор данных, имеющий вид упакованных строк, закачивается специальным знаком "конец файла" <26>.

Файлы - программы, доступные процессору, т.е. могут сразу исполнены, имеют расширения .COM или .EXE . Имена таких файлов служат командами исполнения содержимого для операционной системы. Операционная система (ОС) - специальная программа, автоматически запускаемая при включении компьютера, основным назначением которой является поиск и исполнение файлов-программ.

Файлы - программы на языке "Pascal" - содержат текст программы, являются строками. Могут быть созданы с помощью любого текстового редактора. С помощью программы-транслятора могут быть преобразованы в файлы, исполняемые процессором.

Обычно специальный редактор объединяют с транслятором, куда добавляются средства контроля программ и систему подсказок (Help) -

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

По стандарту языка "BASIC", для выполнения программ обязательно требуется присутствие BASIC-системы. При работе которой оператор находится в среде специального редактора. Набираемые команды могут быть выполнены немедленно, или, если имеют метку - номер, запомнены в оперативной памяти. Команды оперативной памяти

могут быть просмотрены командой "LIST" или исполнены командой "RUN" Из оперативной памяти программа может быть перенесена во внешнюю командой SAVE"<ИМЯ ФАЙЛА>"[,A]

Запись присходит в более коротком кодированном варианте или (при наличии флажка - буквы "A" в команде) в полном варианте, пригодном для просмотра и печати средствами ДОС.

Командой восстановления программы в оперативную память из файла является LOAD"<ИМЯ ФАЙЛА>"[,R]

Флаг 'R' служит для немедленного запуска программы после "загрузки". Загрузить в оперативную память и сразу исполнить программу можно командой RUN"<ИМЯ ФАЙЛА>"

Обычно, файл - программа на языке "BASIC" имеет расширение .BAS . Запись/загрузка подпрограмм в кодах проводится командами BSAVE"<имя>" BLOAD"<имя>"

При работе с кассетным магнитофоном в качестве ВУ, используют команды CSAVE"<имя>" CLOAD"<имя>"

Есть возможность объединения двух текстов - программ в один. Для этого один текст должен быть в оперативной памяти, а другой, заранее подготовленный, должен быть записан в файл в полном варианте. Команда MERGE"<имя подготовленного файла>" создаст в оперативной памяти совместный текст обеих программ. Если в склеиваемых текстах были строки с одинаковами номерами, то останется только строка подготовленного файла.

Итак, на примере работы с файлами-программами на языке "BASIC", имеем три вида работы с файлами - создание (SAVE), чтение (LOAD) и добавление (MERGE).

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

должно быть указано число одновременно открытых файлов MAXFILES=<N>, по умолчанию, это число =1. Каналы связи программы с файлом нумеруются, номера используются в командах. В файлах могут быть только данные базовых типов.

В языке PASCAL вместо номеров каналов связи вводятся переменные файлового типа, которые описываются как

:file of <тип элементов>; или :text;

Элементы файлов могут быть любых типов, кроме файлового. Слово "text" указывает на файл строк произвольной длины.

*Способ образования (хранения). <цифры приведены для ЭВМ "Yamaha"> В памяти компьютера, для каждого файла, выделяется буфер <256 байт> При создании файла последовательного доступа, заполняется не файл, а буфер. По заполнении буфера, все его содержимое копируется во внешне устройство (файл), буфер очищается и готов заполняться снова. При чтении, часть содержимого файла, копируется в буфер, откуда читается программой. По мере необходимости, в буфер считываются очередные порции информации.

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

Для работы буфера используются служебная информация - блок управления файлом (File Control Blok - FCB) <9 байт>

*Для работы с текстами обычно используют специальный редактор.

Для работы с файлами данных в языке BASIC, в начале программы должно быть указано число одновременно открытых файлов MAXFILES=<N>, по умолчанию, это число =1. Каналы связи программы с файлом нумеруются, номера используются в командах.

В языке PASCAL вместо номеров каналов связи вводятся переменные файлового типа, которые описываются как :text;

3 Основные операции.

С файлами проделывают две операции: открывают с какой-то целью и закрывают. (file - папка (англ)). Существуют три цели открытия файла - для занасения в него данных (заново)

-для добавления в него данных (в конец)

-для извлечения из него информации.

BASIC

PASCAL открыть

open "<имя>" for output as#1

rewrite(f) для записи

open "<имя>" for input as#1

reset(f) для чтения

open "<имя>" for append as#1

append(f) для добавления

close(#1)

close(f)

закрыть

После открытия файла стандартные команды получения и вывода информации, при наличии указания на номер или имя канала связи, работают с файлом:

PRINT #1, A;B

WRITE(f,A,B); WRITELN(f,A,B);

INPUT #1, X,Y

READ(f,X,Y); READLN(f,X,Y);

В языке PASCAL файловая переменная перед использованием связывается с именим файла - строкой знаков специальной командой ASSIGN(f,<имя>);

4 Связь с данными других типов. Элементом текста является строка.

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

Файлы программ считаются двоичными. В них хранятся байты кодов команд процессора (в двоичной форме).

15.Указатели

Динамическая память -- это оперативная память ПК, предоставляемая программе при ее работе, за вычетом сегмента данных (64 Кбайт), стека (обычно 16 Кбайт) и собственно тела программы. Размер динамической памяти можно варьировать в широких пределах. По умолчанию этот размер определяется всей доступной памятью ПК и, как правило, составляет не менее 200...300 Кбайт.

АДРЕСА И УКАЗАТЕЛИ

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

В ПК адреса задаются совокупностью двух шестнадцатиразрядных слов, которые называются сегментом и смещением. Сегмент -- это участок памяти, имеющий длину 65536 байт (64 Кбайт) и начинающийся с физического адреса,

кратного 16 (т.е. 0, 16, 32, 48 и т.д.). Смещение указывает, сколько байт от начала сегмента необходимо пропустить, чтобы обратиться к нужному адресу.

Адресное пространство ПК составляет 1 Мбайт (речь идет о так называемой стандартной памяти ПК; на современных компьютерах с процессорами 80386 и выше адресное пространство составляет 4 Гбайт, однако в Турбо Паскале нет средств, поддерживающих работу с дополнительной памятью; при использовании среды Borland Pascal with Objects 7.0 такая возможность имеется). Для адресации в пределах 1 Мбайта нужно 20 двоичных разрядов, которые получаются из двух шестнадцатиразрядных слов (сегмента и смещения) следующим образом: содержимое сегмента смещается влево на 4 разряда, освободившиеся правые разряды заполняются нулями, результат складывается с содержимым смещения.

Схема формирования адреса в ПК

Фрагмент памяти в 16 байт называется параграфом, поэтому можно сказать, что сегмент адресует память с точностью до параграфа, а смещение -- с точностью до байта. Каждому сегменту соответствует непрерывная и отдельно адресуемая область памяти. Сегменты могут следовать в памяти один за другим без промежутков или с некоторым интервалом, или, наконец, перекрывать друг друга.

Таким образом, по своей внутренней структуре любой указатель представляет собой совокупность двух слов (данных типа WORD), трактуемых как сегмент и смещение. С помощью указателей можно размещать в динамической памяти любой из известных в Турбо Паскале типов данных. Лишь некоторые из них (BYTE, CHAR, SHORTINT, BOOLEAN) занимают во внутреннем представлении один байт, остальные -- несколько смежных. Поэтому на самом деле указатель адресует лишь первый байт данных.

ВЫДЕЛЕНИЕ И ОСВОБОЖДЕНИЕ ДИНАМИЧЕСКОЙ ПАМЯТИ

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

Начало кучи хранится в стандартной переменной HEAPORG, конец - в переменной HEAPEND. Текущую границу незанятой динамической памяти указывает указатель HEAPPTR.

Расположение кучи в памяти ПК

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

var

i, j: ^integer; r: ^real; begin

New(i);

. . . . .

end.

После выполнения этого фрагмента указатель i приобретет значение, которое перед этим имел указатель кучи HEAPPTR, а сам HEAPPTR увеличит свое значение на 2, так как длина внутреннего представления типа INTEGER, с которым связан указатель i, составляет 2 байта (на самом деле это не совсем так: память под любую переменную выделяется порциями, кратными 8 байтам). Оператор

new(r);

вызовет еще раз смещение указателя HEAPPTR, но теперь уже на 6 байт, потому что такова длина внутреннего представления типа REAL. Аналогичным образом выделяется память и для переменной любого другого типа. После того как указатель приобрел некоторое значение, т.е. стал указывать на конкретный физический байт памяти, по этому адресу можно разместить любое значение

соответствующего типа. Для этого сразу за указателем без каких-либо пробелов ставится значок ^, например:

i^ := 2; {В область памяти i помещено значение 2}

r^ := 2*pi; {В область памяти r помещено значение 6.28}

Таким образом, значение, на которое указывает указатель, т.е. собственно данные, размещенные в куче, обозначаются значком ^, который ставится сразу за указателем. Если за указателем нет значка ^, то имеется виду адрес, по которому размещены данные. Имеет смысл еще раз задуматься над только что сказанным: значением любого указателя является адрес, а чтобы указать, что речь идет не об адресе, а о тех данных, которые размещены по этому адресу, за указателем ставится ^. Если Вы четко уясните себе это, у Вас не будет проблем при работе с динамической памятью.

Динамически размещенные данные можно использовать в любом месте программы, где это допустимо для констант и переменных соответствующего типа, например:

r^ := sqr(r^) + i^ - 17;

Разумеется, совершенно недопустим оператор r := sqr(r^) + i^ - 17;

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

r^ := sqr(r);

поскольку значением указателя R является адрес, и его (в отличие от того значения, которое размещено по этому адресу) нельзя возводить в квадрат. Ошибочным будет и такое присваивание:

r^ := i;

так как вещественным данным, на которые указывает R, нельзя присвоить значение указателя (адрес).

Динамическую память можно не только забирать из кучи, но и возвращать обратно. Для этого используется процедура DISPOSE. Например, операторы dispose(r);

dispose(i);

вернут в кучу 8 байт, которые ранее были выделены указателям I и R. Отметим, что процедура DISPOSE(PTR) не изменяет значения указателя PTR, а

лишь возвращает в кучу память, ранее связанную с этим указателем. Однако повторное применение процедуры к свободному указателю приведет к

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

р: ^real = NIL; begin

. . . . .

if р = NIL then new(p);

. . . . .

dispose(p); p := NIL;

. . . . .

end.

Никакие другие операции сравнения над указателями не разрешены. Приведенный выше фрагмент иллюстрирует предпочтительный способ объявления указателя в виде типизированной константы с одновременным присвоением ему значения NIL. Следует учесть, что начальное значение указателя (при его объявлении в разделе переменных) может быть произвольным. Использование указателей, которым не присвоено значение процедурой NEW или другим способом, не контролируется системой и может привести к непредсказуемым результатам. Чередование обращений к процедурам NEW и DISPOSE обычно приводит к ╚ячеистой╩ структуре памяти. Дело в том, что все операции с ней выполняются под управлением особой подпрограммы, которая называется администратором кучи. Она автоматически пристыковывается к нашей программе компоновщиком Турбо Паскаля и ведет учет всех сводных фрагментов в куче. При очередном обращении к

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

Другая возможность состоит в освобождении целого фрагмента кучи. С этой целью перед началом выделения динамической памяти текущее значение указателя HEAPPTR запоминается в переменной-указателе с ющью процедуры MARK. Теперь можно в любой момент освободить фрагмент кучи,

начиная от того адреса, который запомнила процедура MARК, и до конца динамической памяти. Для этого используется процедура RELEASE. Например:

var

p,p1,p2,р3,р4,р5: ^integer; begin

new(p1);

new(p2);

mark(p);

new(p3);

new(p4);

new(p5);

. . . . .

release(p); end.

В этом примере процедурой MARK(P) в указатель Р было помещено тукущее значение HEAPPTR, однако память под переменную не резервировалась. Обращение RELEASE(P) освободило динамическую память от помеченного места до конца кучи. Пирведенный ниже рисунок иллюстрирует механизм работы процедур NEW-DISPOSE и NEW-MARK-RELEASE для рассмотренного примера и для случая, когда вмемто оператора RELEASE(P) используется, например, DISPOSE(P3).

а) б) в)

Состояние динамической памяти:

а) перед освобождением; б) после Dispose(p3); в) после Release(p)

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

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

16. Перечислимый, ограниченный типы данных. Типы данных вводимые пользователем.

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

Например, Var a: 1..25; ch: 'a' ..'z';

Здесь переменные а и ch могут принимать значения только из указанного интервала; базовым типом для переменой а является целый тип, а для переменной ch - символьный. Переменная ограниченного типа сохраняет все свойства переменных базового типа. Для чего вводится ограниченный тип данных? Использование ограниченного типа делает программу наиболее понятной и наглядной. Например, если в программе переменная b может принимать только значения 3, 4, 5, 6, 7, 8, то лучше описать её следующим образом:Var b: 3..8;, чем Var b: Integer; так как в случае выхода значения b за диапазон 3..8 в первом случае будет выдано диагностическое сообщение, которое поможет найти ошибку. Во втором случае будет получен неправильный результат, что затруднит поиск ошибки. Таким образом, второй вариант описания переменной следует использовать в тех случаях, когда диапазон значений заранее неизвестен либо занимает весь допустимый интервал значений для рассматриваемого типа.

Пример : Напишите программу, которая переменной t присваивает значения true, если первая дата предшествует (в рамках года) второй дате, и значение false в противном случае.

Решение Так как в условии задачи оговаривается, что обе даты должны находится в рамках года, то дата должна задаваться днём и месяцем. Количество любого месяца года не может быть более 31, количество месяцев в году равно 12. Значение переменной t равно true, если номер первого месяца меньше второго, либо значение первого дня меньше второго при условии, что номера месяцев совпали.

Program ;

Var d1, d2 : 1..31; m1,m2: 1..12; t:Boolean;

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]