Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
вот оно.docx
Скачиваний:
6
Добавлен:
25.09.2019
Размер:
1.75 Mб
Скачать

28 Проверка операций ввода-вывода

По умолчанию при выполнении операций ввода-вывода осуществляется

их стандартная проверка системными средствами. Для управления проверкой

служит опция компилятора {$I} – проверка вывода-ввода, которая умолчанию включена ({$I+}). При этом, если произошла ошибка ввода-вывода,

то выполнение программы прерывается и выдается сообщение о типе ошибки.

Если нежелательно, чтобы выполнение программы прерывалось по ошибке ввода-вывода, то есть если мы сами хотим обрабатывать данные ошибки, необхотимо отключить стандартную проверку ввода-вывода. С этой целью в тексте программы перед теми операциями ввода-вывода, которые программист желает контролировать сам, необходимо отключить стандартную проверку ввода-вывода опцией {$I-}, а после этих операций снова включить ее опцией {$I+}.

Для контроля операций ввода-вывода в состоянии {$I-} служит специальная функция IOResult (без параметров).

Функция IOResult возвращает целочисленное значение типа Word, которое является состоянием последней выполненной операции ввода-вывода. Если ошибки ввода-вывода не было, то функция возвращает значение ноль, в противном случае – код ошибки.

Если опция {$I} находится в состоянии {$I-} и при некоторой операции ввода-вывода произошла ошибка, то последующие операции ввода-вывода, используемые до вызова функции IOResult, будут игнорироваться.

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

Пример 5.11.

Использование функции IOResult для проверки наличия внешнего файла.

Var

F: File Of Char; Begin

Assign (F, ’PRIMER);

{$I-} Reset(F);

{$I+}

If IOResult = 0 Then

Writeln (Размер файла:’, Filesize (F), байт’)

Else

Writeln (Файл не обнаружен’);

End.

29 Ссылочный тип. Назначение. Синтаксис задания. Представление в памяти. Виды указателей. Операции над указателями.Общие сведения

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

программы.

Для работы с динмическими переменными предусмотрен ссылочный тип (тип указатель). Значением этого типа

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

Синтаксическая диаграмма задания типа указатель имеет вид, который представляет рисунок 6.1.

На данной диаграмме <Идентификатор_типа> - это тип динамически размещаемой переменной. В качестве типа может быть использовано имя стандартного или описанного отдельно типа. Из диаграммы видно, что в Паскале имеется два вида указателей указатель на элемент некоторого типа (верхнее ребро синтаксической

диаграммы) и указатель, не связанный с типом (Pointer).

Пример 6.1.

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

Type

Mas = Array [1..10] Of Integer;

Admas = ^Mas; {Admas – тип указателя на массив типа Mas}

P1 = ^Integer; {P1 – тип указателя на тип Integer}

Var

P: ^Integer; {в указателе P будет храниться адрес типа Integer }

Q: ^Char;

Pp: P1;

Pt: Pointer;

Adrm: Admas;

Указатели являются автоматическими переменными ссылочного типа.

Динамические переменные не объявляются в программе. Поэтому единственным средством доступа к ним являются указатели.

Связь указателя Р с динамической переменной схематически отображает

рисунок 6.2.

Указатель занимает четыре байта памяти.

Иногда необходимо в качестве значения указателя принять пустую ссылку – ссылку, которая не связывает с данным указателем никакой

динамической переменной. Для этого служит предопределенная константа Nil.

Константа Nil является совместимой по типу с любым типом указателя.

Например, для указателей, объявленных в примере 6.1, можно записать:

Pt := Nil;

P := Nil;

Q := Nil; Adrm := Nil;

Над значениями ссылочного типа в Паскале нет операций, которые

давали бы результат этого же типа.

Над значениями ссылочного типа определены только присваивание и две операции сравнения: = и <>.

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

При присваивании значения ссылочной переменной в правой части оператора присваивания используется ссылочное выражение того же типа, что

и тип переменной в левой части. В качестве ссылочного выражения может использоваться: пустая ссылка Nil; ссылочная переменная; ссылочная функция (функция, значением которой является ссылка).

Например, встроенная функция Addr(X) – возвращает адрес элемента X. Здесь X – любая переменная, процедура или функция. Результат функции Addr(X) совместим по присваиванию со всеми типами “указатель”. Поэтому

можно, например, написать такие операторы присваивания (для переменных

типа указатель, объявленных в примере 6.1):

Pt := Addr (А); {А может иметь любой тип}

P := Addr ); {В должна иметь тип Integer}

Объявление ссылочной переменной в разделе Var не порождает самой

динамической переменной. По этому объявлению транслятор только отводит место в памяти для размещения ссылки (адреса динамической переменной).

30 Процедуры New и Dispose

Для порождения динамической переменной используется стандартная

процедура New(P). Здесь P – это ссылочная переменная любого типа.

Данная процедура размещает динамическую переменную типа указателя. Переменной выделяется память, достаточная для хранения наиболее длинного значения типа указателя. Адрес начала данного места памяти присваивается

заданной ссылочной переменной P.

Пример 6.2.

Использование процедуры New.

Var

P: ^Integer;

...

Begin

New (P);

...

В данном примере процедру New пораждает динамическую переменную типа Integer, адрес этой переменной присваивается указателю P.Для динамической переменной процедура New играет ту же роль, что

раздел описаний Var для автоматической переменной. Никакого значения процедура New динамической переменной не присваивает.Для обращения к динамической переменной используется переменная с указателем, синтаксис которой представляет рисунок 6.3.

Символ ^ называется знаком карата.Например, (в применении к примеру 6.2) обращение к динамической переменной, связанной с указателем Р, осуществляется с помощью переменной с указателем:

P^ := 15; {Р^ - переменная с указателем; динамической переменной типа Integer, связанной с указателем P, присвоено значение 15}

Над переменными с указателями пределены любые операции допустимые для переменных того типа, что и тип динамической переменной.

Пример 6.5.

Работа с указателями и с динамическими переменными.

Var

X, Y: ^Integer;

Begin

New (X);

New (Y);

X^ := 5;

Y^ := 10;

X := Y;

Y := Nil;

Для уничтожения динамических переменных (освобождения занимаемой ими памяти) используется стандартная процедура Dispose (P).

В результате выполнения процедуры Dispose(P) динамическая переменная, связанная с указателем P, уничтожается, занимаемая ею память считается свободной, значение P считается неопределенным (равным Nil).

Процедура Dispose уничтожает только саму динамическую переменную, но не указатель на нее.

...

New (X);

New (Y);

X^ := 5; Y^ := 10; Dispose (X);

X := Y;

Y := Nil; {Освобождается область памяти, занятая

динамической переменной X^}

...

31 Процедуры Getmem и Freemem

Использование процедур Getmem и Freemem – это второй метод работы с динамическими переменными.Вызов процедуры Getmem имеет следующий формат:Getmem (P, Size);Здесь P - указатель любого типа, Size – выражение типа WordПроцедура Getmem выделяет из Heap-области (хип-область, область кучи,область динамической памяти) блок памяти заданного размера Size (порождает динамическую переменную размера Size) и адрес этого блока присваивает ссылочной переменной P. Максимальный размер блока – 65521байт (64К байта $F (смещение)). Для освобождения блока памяти занимаемой динамической

переменной , используется процедура Freemem:

Freemem (P, Size)

Здесь P – указатель произвольного типа, которому предварительно было присвоено значение процедурой Getmem или оператором присваивания; значение Size должно точно соответствовать размеру переменной, размещенной до этого процедурой Getmem.

Процедура Freemem уничтожает динам. Переменную P^, занимаемая ею память считается своб., значение Р становится неопределенным. Таким образом действие процедур Getmem/Freemem, аналогично действию процедур New/Dispose – порождается и уничтожается динам переменная.

Пример 6.8

Эквивалентные фрагменты программ, использующие процедуры Getmem/Freemem и New/Dispose.

Type

T = <Тип>; Var

P: ^T;

Begin

New (P); Getmem (P, Sizeof(T));

… Эквивалентны

Dispose (P); Freemem (P, Sizeof(T));

В общем случае процедуры Getmem/Freemem дают большую свободу действий по сравнению с процедурами New/Dispose, так как позволяют работать без привязки к конкретному типу переменных.

Пример 6.9.

Использование процедур Getmem/Freemem. Различная интерпретация выделенной области памяти.