Нетипизированные файлы объявляются как файловые переменные типа FILE и отличаются тем, что для них не указан тип компонентов. Отсутствие типа делает эти файлы, с одной стороны, совместимыми с любыми другими файлами, а с другой - позволяет организовать высокоскоростной обмен данными между диском и памятью.
При инициации нетипизированного файла процедурами RESET или REWRITE можно указать длину записи нетипизированного файла в байтах. Например, так:
Var
f: file;
Begin
.........
assign (f, ‘myfile.dat’);
reset (f, 512);
.........
End.
Длина записи нетипизированного файла указывается вторым параметром при обращении к процедурам RESET или REWRITE, в качестве которого может использоваться выражение типа WORD. Если длина записи не указана, она принимается равной 128 байтам.
Турбо Паскаль не накладывает каких-либо ограничений на длину записи нетипизированного файла, за исключением требования положительности и ограничения максимальной длины 65535 байтами (емкость целого типа WORD).
При работе с нетипизированными файлами могут применяться все процедуры и функции, доступные типизированным файлам, за исключением READ и WRITE, которые заменяются соответственно высокоскоростными процедурами BLOCKREAD и BLOCKWRITE. Для вывоза этих процедур используются следующие предложения:
|
|
BLOCKREAD (<ф.п.>, <буф>, <[,<NN>])
BLOCKWRITE (<ф.п.>, <буф>, <[,<NN>])
Здесь <буф> - буфер: имя переменной, которая будет участвовать в обмене данными с дисками;
<D> - количество записей, которые должны быть прочитаны или записаны за одно обращение к диску;
<NN> - необязательный параметр, содержащий при выходе из процедуры количество фактически обработанных записей.
За одно обращение к процедурам может быть передано до N*RECS байт, где RECS - длина записи нетипизированного файла. Передача идет, начиная с первого байта переменной <буф>. Программист должен позаботится о том, чтобы длина внутреннего представления переменной <буф> была достаточной для перемещения всех N*RECS байт при чтении информации с диска. Если при чтении указана переменная <буф> недостаточной длины или если в процессе записи на диск не окажется нужного свободного пространства, возникнет ошибка ввода-вывода, которую можно заблокировать, указав необязательный параметр <NN> (переменная типа WORD).
После завершения процедуры указатель смещается на <NN> записей. Процедурами SEEK, FILEPOS и FILESIZE можно обеспечить доступ к любой записи нетипизированного файла.
Тема № 11: «Процедуры и функции»
В языке Паскаль определяются два типа подпрограмм - процедуры и функции. Любая подпрограмма обладает той же структурой, которой обладает и вся программа.
|
|
При вызове подпрограммы выполнение основной программы приостанавливается и управление передается в подпрограмму. По окончании работы подпрограммы управление предается остальной программе.
Основное различие между процедурой и функцией состоит в том, что процедура только выполняет какую - либо законченную последовательность действий, не возвращая результата работы в основную программу, а функция и выполняет действия, и возвращает результат.
Любая подпрограмма должна быть описана до того, как она будет вызвана в программе или в другой подпрограмме Все переменные, которые использует подпрограмма, могут быть либо глобальными, т.е. объявленные в основной программе и доступные как программе, так и всем ее подпрограммам, либо локальными, т.е. объявленные внутри подпрограммы и доступные только ей собой. Обмен данными между основной программой и подпрограммой может осуществляться только с помощью глобальных переменных.
Подпрограмма может непосредственно использовать любые глобальные переменные за исключением тех, которые имеют те же имена, что и ее локальные переменные.
11.1. Процедуры
Любая процедура начинается с заголовка, который является обязательным. Он состоит из зарезервированного слова PROCEDURE, за которым следует идентификатор имени процедуры, а далее в круглых скобках - список формальных параметров:
PROCEDURE <имя процедуры> (<список формальных параметров>);
За заголовком следуют такие же разделы, что и в основной программе.
При вызове процедуры необходимо указать ее имя и в круглых скобках список фактических параметров, которые должны совпадать по количеству и типам с формальными параметрами. Все формальные параметры можно разбить на 4 категории:
- параметры - значения - эти параметры в основной программе подпрограммой не изменяются;
- параметры - переменные - эти параметры подпрограмма может изменить в основной программе;
- параметры - константы;
- параметры - процедуры и параметры - функции.
Параметры - значения передаются основной программой в подпрограмму через стек в виде их копий, и, следовательно, собственный параметр программы подпрограммой измениться не может. Параметр- значение указывается в заголовке подпрограммы под своим именем и - через двоеточие - типом.
При передаче параметров - переменных в подпрограмму фактически передаются их адреса в порядке, объявленном в заголовке подпрограммы. Это означает, что подпрограмма имеет доступ к этим параметрам и может их изменять.
Параметр- переменная указывается в заголовке подпрограммы аналогично параметру - значению, но только перед именем параметра записывается зарезервированное слово VAR. Действие слова VAR распространяется до ближайшей точки с запятой, т.е. в пределах одной группы.
Параметр-константа указывается в заголовке подпрограммы подобно параметру- значению, но перед именем параметра записывается зарезервированное слово CONST, действие которого распространяется до ближайшей точки с запятой. Параметр-константу нельзя передавать в другую подпрограмму в качестве фактического параметра.
11.2. Функции
Общая структура функций совпадает со структурой процедуры, за исключением заголовка. Заголовок функции имеет следующий вид:
FUNCTION<имя функции> (<список параметров>):<тип возвращаемого результата>;
Функции - это процедуры особого характера, результатом работы которых является некоторое значение, подобное переменной. Функция, как и процедура, может иметь список параметров, следующих за именем функции в круглых скобках. Но если имя процедуры используется только для ее вызова, то с именем функции связывается ее значение. На примере сложения двух целых чисел покажем различия при использовании процедур и функций
|
|
Program Sums;
Var
a,b, Sum, Sum_Number: Integer;
Procedure Summ1 (Var Sum: Integer; a,b: integer);
Begin
Sum:=a+b;
End;
Function Summ2(a,b: integer): integer;
Begin
Summ2:=a+b;
End;
Begin
a:=12; b:=5; {Установка начальных значений переменных «а» и «b»}
{Суммирование чисел с использованием процедуры}
Summ1 (Sum_Number, a,b);
WriteLn (‘Сумма чисел равна = ’, Sum_Number);
{Суммирование чисел с использованием функции}
Sum_number:= Summ2(a,b);
WriteLn (‘Сумма чисел равна:’, Sum_Number);
WriteLn (‘Сумма чисел равна:’, Summ2(a,b));
End.
Тема №12: Указатели и динамическая память.
Динамическая память – это оперативная память ПК, предоставляемая программе при ее работе, за вычетом сегмента данных (область оперативной памяти, где размещены все переменные), стека (16 кб), и тела программы.
При динамическом размещении данных заранее не известны ни тип, ни количество размещаемых данных. К ним нельзя обращаться по именам, как к статическим переменным. Для управления динамической памятью используются указатели. Указатель – это переменная, которая в качестве своего значения содержит адрес байта памяти. С помощью указателя можно размещать в динамической памяти любой тип данных. Кроме того, указатели могут ссылаться на ещё не описанный тип данных.
Существует два вида указателей: типизированные и нетипизированные.
VAR
a: ^INTEGER; - типизированный (указатель типа INTEGER)
b: ^POINTER; - нетипизированный.
Нетипизированные указатели используются для размещения данных, структура и тип которых меняются во время работы программы.
Присваивать значение одного типизированного указателя другому можно, только если они связаны с одним типом данных.
VAR a, b: ^Integer;
c: ^real; d: pointer;
____________________
a:=b; - ПРАВИЛЬНО
a:=c; - НЕ ПРАВИЛЬНО
d:=b; a:=d; - ПРАВИЛЬНО
12.1. Выделение и освобождение динамической памяти.
Вся динамическая память рассматривается как сплошной массив байтов, который называется кучей. Начало кучи хранится в стандартной переменной HEAPORG, конец – в переменной HEAPEND. Текущую границу незанятой динамической памяти указывает указатель HEAPPTR.
Выделение динамической памяти происходит при помощи процедуры NEW(<указатель>). Указатель приобретает адрес, начиная с которого можно разместить данные. Для этого сразу за указателем ставится значок ^.
|
|
VAR A:^Integer; B:^Real;
Begin
New(A);
A^:= 649;
Если бы за переменной А не было значка ^, то переменной А присваивался бы адрес, по которому впоследствии будут размещены данные.
Высвобождение динамической памяти происходит при помощи процедуры DISPOSE(<указатель>); При этом значение самого указателя (адрес) не изменяется.
Попеременное обращение к процедурам NEW и DISPOSE часто приводит к образованию «дыр» в памяти. Для освобождения целого фрагмента кучи используется процедура MARK, которая запоминает текущее значение указателя HEAPPTR. Далее в любом месте программы можно освободить фрагмент кучи начиная с данного адреса и до конца динамической памяти при помощи процедуры RELEASE. Не рекомендуется, однако использовать RELEASE совместно с процедурой DISPOSE.
Для работы с нетипизированными указателями используются процедуры:
GETMEM (A, Size) – резервирование памяти,
FREEMEM (A, Size) – освобождение памяти,
где А – нетипизированный указатель,
Size – размер в байтах.
{Некоторые процедуры и функции для работы с динамической памятью}
Тема № 13: Модули.
Модуль – это автономно компилируемая программная единица, включающая в себя различные компоненты раздела описаний (типы, константы, переменные, процедуры и функции) и, возможно, некоторые исполняемые операторы инициирующей части. Модули позволяют разрабатывать библиотеки прикладных программ. Программный код модулей размещается в отдельном сегменте памяти. Максимальная длина сегмента не превышает 64кб, однако, количество одновременно используемых модулей ограничивается лишь доступной памятью, что позволяет создавать очень крупные программы. Модуль состоит из заголовка и трех частей, каждая из которых может быть пустой.
UNIT <имя>;
INTERFACE
<интерфейсная часть>
IMPLEMENTATION
<исполняемая часть>
BEGIN
<инициирующая часть>
END.
Имя заголовка модуля должно совпадать с именем дискового файла, в который помещается исходный текст модуля. Т.е. если заголовок UNIT INFORM, то текст модуля должен находиться в файле INFORM.PAS. Имя модуля связывает его с другими модулями и с основной программой при помощи предложения USES <список модулей>.
Например: USES CRT, GRAPH, INFORM;
Предложение USES в модулях находится либо сразу за словом INTERFACE, либо за словом INMPLEMENTATION, либо и там и там.
В интерфейсной части содержаться объявления всех глобальных объектов модуля, доступные основной программе и другим модулям. При объявлении глобальных подпрограмм в интерфейсной части указываются только их заголовки.
Исполняемая часть содержит описание подпрограммы, объявленной в интерфейсной части. В ней могут быть объявлены локальные для модуля объекты.
Инициирующая часть завершает модуль. Она может отсутствовать вместе с начинающим ее словом BEGIN или быть пустой. Здесь размещаются операторы, которые обычно используются для подготовки работы программы.