Лекция 13. Работа с файлами. Обработка ошибок в Паскаль.

Записи

Лекция 12. Типы данных, определяемые пользователем. Записи.

 

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

вид:

Type

Type1_ID = Type_description;

где Type1_ID – идентификатор типа, определяемый пользователем, а Type_description – представляет собой описание соответствующего типа.

Type

Index = 1..100;

List121 = array[0..120] of Word;

List121by8 = array [1..8] of List121;

PersonData = record

Name, firstName: string [40];

Age: Word;

Married: boolean;

IQ: (High, medium, low, to_be_neglected);

End;

В этом примере программист сам определяет свои собственные типы: Index – интервал целочисленных значений от 1 до 100, List121 – массив из 121 значения типа Word, List121by8 – двумерный массив, представляющий собой таблицу 121х8, PersonData – тип запись. Далее идентификаторы типов можно использовать для описания переменных в разделе Var.

Var

In1, In2: Index;

Data: List121;

Ivanoff, Petroff: PersonData;

 

 

Комбинированные типы, как и регулярные типы, представляют собой правило формирования составных типов. В отличие от массивов, записи позволяют объединять значения различных типов и поэтому являются наиболее гибким механизмом построения данных.

Необходимо описать атрибуты (характеристики) некоторого объекта, представляемого и обрабатываемого в программе. Во всех подобных ситуациях атрибуты объекта представляются значениями различных типов и поэтому для их описания не могут быть использованы массивы. Для описания объекта 'студент' могут понадобиться следующие характеристики:

· Фамилия, имя и отчество (символьные массивы или строки).

· Пол (перечислимый тип из двух значений).

· Индекс специальности (целое).

Описание комбинированного типа представляет собой список описаний его элементов (которые называются также полями записи); каждое описание похоже на описание простой переменной. Список полей начинается служебным символом record и завершается end.

Type

Person = record

Name, secondName, SurName: string[20];

Sex: (mole, Femole);

Speciality :word;

End;

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

Var

Sasha, Masha:Parson;

Доступ к элементам (полям) записей производится с помощью конструкции, называемой селектор записи и имеющий следующий вид: R.F,
где R - переменная комбинированного типа, F - идентификатор поля. Допустимы следующие конструкции:

Sasha.Name:= 'Александр';

Masha.Name :='Мария';

Sasha.Sex := 'Male';

Masha.Sex := 'female';

Masha.Speciality := Sasha.Speciality;

Комбинированные типы можно использовать для построения более сложных структур, например, массивов, состоящих из записей. Первый случай:

Var

Group : array [1..10] of person;

DataBase : file of person;

Для переменной Group доступ к полям записей, составляющих этот массив, производится следующим образом:

Group[i].Sex:=Female;

If Group[j].Name = 'Борис' then

Writeln(Group[j].SurName);

Второй случай: пусть для комбинированного типа Person необходимо хранить информацию о дате рождения.

Type

Date = record

Month : (Jan, Feb, Mar, Apr,…);

Day : 1..31;

Year :1900..2000;

End;

К записи Person добавляем

…..

BirthDay : Date;

End;

Доступ к полям из элемента BirthDay производится по общим правилам, например:

Sasha.BirthDay.Year : = 1970;

Masha.BirthDay.Month : = Feb;

При записи селектора необходимо помнить, что слева от символа 'точка' всегда должна находиться переменная типа запись (Sasha.BirthDay), а справа идентификатор поля этой записи. Пример использования записей в математике - комплексные числа.

Type

Comptex = record

Re, Im : real;

End;

Далее можно определить операции над комплексными числами (сложение, умножение, деление).

Procedure Addc(c1, c2 :complex; var R : complex);

 

Записи с вариантами.

Часто необходимо в пределах одной записи иметь различную информацию в зависимости от конкретного значения некоторого поля.

Рассмотрим тип Person, если в поле Sex (пол) имеет значение Male (мужской), то пусть необходимо предусмотреть такие поля:

· Время очередных военных сборов.

· Курит или нет.

Если поле содержит Famale (женский), то хотелось бы знать цвет глаз. Это можно было бы определить двумя отдельными комбинированными типами. Однако это сильно затруднит программирование. Любой комбинированный тип, помимо фиксированного списка полей, может содержать вариантную часть, предполагающую определение нескольких вариантов структуры этого типа. Различие может касаться как числа компонент, так и их типа.

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

Type

Person Sex = (Mole, Famole);

Person = record

Name : string[20];

Speciality : Word;

BirthDay : Date;

Case Sex : personSex of

Mole : (Army : date; Smoking : boolean);

Femole : (EyesColor : (Blue, Brown, …));

End;

4. В определении комбинированного типа может быть только одна вариантная часть и она должна быть задана в конце записи.

5. Альтернативы вариантной части помечаются допустимыми значениями поля Sex; определение этого поля вынесено из фиксированной части и помещено в заголовке вариантной части (поле - дискриминант).

6. Идентификаторы полей во всех вариантах должны быть различны и отличаться от идентификаторов полей фиксированной части.

7. Для некоторых значений поля - дискриминанта вариант может отсутствовать. Тогда после двоеточия может стоять пустой список всегда ().

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


 

13.1 Файловые типы

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

Var

F: file of integer;

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

Рисунок 13.1 – Структура файла

Начальный элемент файла - нулевой! Базовый тип может быть любым за исключением файлового и комбинированного, с одним из полей - файлом.

Операции с файлами можно разбить на четыре основные группы:

8. установочные и завершающие;

9. ввод - вывод;

10. перемещение по файлу;

11. специальные операции.

В первую группу входят четыре операции, реализованные в виде стандартных процедур:

Assign, reset, rewrite, flush, close,..

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

Имя файла строится по правилам, принятым в OS MS DOS.

Assign (f, 'd:/users/is -200/myfile.dta')

Второй параметр процедуры может быть строкой, содержащей условное обозначение 'псевдофайлов' MS DOS, т. е. Связанных с конкретным устройством.

CON - вывод на экран или ввод с клавиатуры;
LPT1, LPT2, LPT3 - вывод на печатающие устройства;
PRN - синоним LPT1;
COM1, COM2 - последовательные коммуникационные карты;
AUX - синоним COM1;
NUL - фиктивное устройство.

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

Разница между этими двумя процедурами заключается в начальных действиях над файлами. Rest предполагает, что открываемый дисковый файл уже существует, в противном случае возникает ошибка. Rewrite допускает, что открываемый файл может еще не существовать. В этом случае процедура создает заданный файл! Если же файл существует, то процедура считывает его.

n Flush (параметр - файловая переменная) используется для завершения обменов с файлом без его закрытия.

n Close завершает действия с файлом, который указывается в качестве ее единственного параметра. При этом ликвидируются внутренние буфера, образованные при открытии. После этого файловую переменную можно связать посредством Assign с каким либо другим дисковым файлом.