Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Паскаль (ст 33).doc
Скачиваний:
2
Добавлен:
13.11.2019
Размер:
821.76 Кб
Скачать

Типизированные файлы

1. Назначение.

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

2. Описание файловых переменных для типизированных файлов.

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

Var

<имя_файловой_переменной> : File of <тип_компонентов>;

где <тип_компонентов> - любой стандартный тип, определенный в Pascal (кроме файлового) либо тип, определенный пользователем в разделе Type (кроме файлового).

Пример.

Type Stroka=Srtring[15];

Var

F1 : File of Integer; {файл с целочисленными компонентами}

F2 : File of Stroka; {файл со строковыми компонентами}

3. Процедуры и функции работы с типизированными файлами.

а) К типизированным файлам применимы процедуры Assign, Reset, Rewrite, Close, Rename, Erase и функция Eof.

б) Функция FileSize.

Назначение:

определение числа компонентов (размера файла).

Синтаксис:

FileSize( F ), где F – файловая переменная.

Описание работы:

  • функция FileSize возвращает целое число в диапазоне от 0 до 231-1, которое равно количеству компонентов в файле;

  • если файл пуст, то функция возвратит 0.

Примечание:

  • аргументом функции не может быть файловая переменная текстового файла;

  • файл должен быть открыт до применения функции.

в) Функция FilePos.

Назначение:

определение текущей позиции указателя обработки.

Синтаксис:

FilePos( F ), где F – файловая переменная.

Описание работы:

  • функция FilePos возвращает целое число в диапазоне от 0 до 231-1, которое равно текущей позиции (или номеру компонента, на который установлен указатель);

  • если текущая позиция соответствует началу файла, то функция возвратит 0;

  • если текущая позиция соответствует концу файла, то FilePos( F ) =

= FileSize( F ).

Примечание:

  • аргументом функции не может переменная текстового файла;

  • файл должен быть открыт до вызова функции.

г) Процедура Seek.

Назначение:

непосредственный доступ к заданному компоненту файла прямого доступа.

Синтаксис:

Seek( F, N ), где F – файловая переменная, N – номер нужного компонента, представляет собой целое число в диапазоне от 0 до 231-1.

Описание работы:

  • процедура Seek перемещает текущий указатель к компоненту с номером N (первый компонент в файле имеет номер 0);

  • для расширения файла предусмотрена возможность перемещения на конец файла, это осуществляется с помощью функции FileSize:

Seek(F, FileSize(F)).

Примечание:

  • процедуру Seek нельзя использовать для текстовых файлов;

  • файл должен быть открыт до вызова этой процедуры.

д) Процедура Truncate.

Назначение:

усечение файла

Синтаксис:

Truncate( F ), где F – файловая переменная.

Описание работы:

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

Примечание:

  • процедура Truncate не может применяться к текстовым файлам;

  • файл должен быть открыт до вызова процедуры.

Задача 1. Создать файл Lab.dat из 20 целых чисел.

Program Dat;

Uses Crt;

Var

F : File of Iinteger;

i, j: Integer;

Begin

Assign(F, ‘Lab.dat’);

{$I-}

Rewrite(F);

{$I+}

If Ioresult <>0

Then Begin

Writeln (‘Нет места на диске’);

Halt;

End;

Randomize;

For i:=1 to 20

Do Begin

j:=Random(100);

Write(F, j);

End;

Close(F);

End.

{файловая переменная}

{рабочие переменные}

{установление связи F с внешним файлом}

{отключение контроля ошибок ввода/вывода}

{открытие файла для записи}

{включение контроля ошибок ввода/вывода}

{если Ioresult 0}

{то вывод «На диске нет места»}

{ и окончание работы программы}

{формирование типизированного файла}

{закрытие файла}

Связь между файловой переменной и внешним файлом устанавливается процедурой Assign. Открытие файла для записи осуществляется процедурой Rewrite. Если на диске нет места, то на экране появляется соответствующее сообщение и файл не создается. При наличии места на диске с помощью оператора For создается файл из 20 целых чисел. При этом каждый раз используется генератор случайных чисел, который инициализируется процедурой Randomize. Запись в файл производится через переменную j, т. к. с помощью процедуры Write (Writeln) в типизированный файл можно записать только значение переменной, выражения в этом случае использовать нельзя.

Задача

Заменить нулем все компоненты с нечетными номерами файла Lab.dat, созданного с помощью программы Dat.

Program Prim;

Uses Crt;

Var

F: File of Iinteger;

Name: String;

Size, i, II, j: Integer;

Procedure Wywod;

Begin

While not Eof(F)

Do Begin

Read(F, J);

Write(J, ‘ ’);

End;

Writeln;

End;

Begin

Repeat

Write(‘Входной файл >’);

Readln(Name);

Assign(F, Name);

{$I-}

Reset(F);

{$I+}

II:= Ioresult;

If II<>0

Then Writeln(‘Файл’,Name,’ не найден’);

Until II=0;

Wywod;

Writeln(‘Для продолжения нажать Enter’);

Readln;

Size:=FileSize(F);

For i:=1 to (Size div 2)

Do Begin

Seek(F, 2*i - 1);

j:=0;

Write(F, j);

End;

Writeln(‘Результирующий файл’);

Seek(F, 0);

Wywod;

Close(F);

Readln;

End.

{файловая переменная}

{имя файла}

{рабочие переменные}

{процедура вывода файла на экран}

{в цикле}

{ввод имени файла Lab.dat}

{установление связь F с внешним файлом}

{отключение контроля ошибок ввода/вывода}

{открытие файла для чтения для записи}

{включение контроля ошибок ввода/вывода}

{присваивание II значения Ioresult}

{если II 0}

{то вывод сообщения «Файл…не найден»}

{постусловие: пока не открыт нужный файл}

{вывод исходного файла}

{Size = число компонентов в файле}

{в цикле по i}

{перемещение указателя к следующему}

{нечетному компоненту}

{замена нулем нечетного компонента}

{конец цикла For}

{перемещение указателя в начало файла}

{вывод полученного файла}

{закрытие файла}

Объяснить (!!!). Открытие файла для чтения осуществляется стандартной процедурой Reset. С помощью процедуры Reset можно также открыть файл для его корректировки. Значение стандартной функции Ioresult присваивается рабочей переменной II, так как после повторного обращения к функции Ioresult (после вывода сообщения «Файл не найден») ее значение меняется, т. к. вывод на экран всегда корректен. Если открывается несуществующий файл на диске, то на экране появится сообщение «Файл не найден» и снова будет запрашиваться имя входного файла. В данном примере надо ввести имя файла Lab.dat. С помощью стандартной функции Filesize определяется число компонентов в файле. Для перемещения указателя обработки к заданному компоненту используется процедура Seek. При определения длины файла оператором

Size:=Filesize(F);

и организации доступа к компонентам файла с помощью операторов вызова процедуры Seek

Seek(F, 2*I-1) (Seek(F, 0))

используются переменная Size типа Integer и выражение 2*i - 1 типа Integer. Для вывода на экран результирующего файла текущую позицию в файле надо переместить в начало. Для этого применяется процедура

Seek(F, 0);

Внутренняя процедура Wywod используется для вывода исходного и результирующего файлов.

Входной файл Lab.dat

61 41 37 91 81 15 60 10 51 5 98 18 32 84 42 46 77 75 99 62

Результирующий файл

61 0 37 0 81 0 60 0 51 0 98 0 32 0 42 0 77 0 99 0

Результаты выполнения программы Prim.

Тип – запись

1. Реальные данные об объектах часто описываются величинами разных типов. Например, товар на складе описывается следующими величинами: наименование (String), количество (Integer), цена (Real), наличие сертификата качества (Boolean) и т. д. В этом случае возникает необходимость хранить и обрабатывать совокупности данных различного типа, поэтому приходится использовать отдельные массивы для каждого типа данных, а для установления соответствия между ними вводятся соответствующие индексы. Такой подход не очень удобен и существенно усложняет написание программы. В Pascal существует другой способ решения таких задач – использование комбинированного типа данных, который называется запись. Запись – это структурированный тип данных, состоящий из фиксированного числа компонентов одного или нескольких типов.

2. Определение типа записи начинается идентификатором Record и заканчивается зарезервированным словом End. Между ними заключен список компонентов, называемых полями, с указанием идентификаторов (имен) полей и типа каждого поля (см. ниже). Тип запись можно описывать:

а) в разделе описания типов

Type

<имя_типа_записи> = Record

<имя_поля_1> : <тип_поля_1>;

< имя_поля_2> : < тип_поля_2>;

< имя_поля_k> : < тип_поля_k>;

End;

Var

<имя_переменной> : <имя_типа_записи>;

б) явно в разделе описания переменных

Var

<имя_переменной> : Record

<имя_поля_1> : <тип_поля_1>;

< имя_поля_2> : < тип_поля_2>;

< имя_поля_k> : < тип_поля_k>;

End;

Пример 1.

Type

Car = Record {объявление записи из 4-х полей}

Number : Integer; {номер}

Marka : String[20]; {марка}

FIO : String[40]; {фамилия и инициалы владельца}

Address : String[60]; {адрес владельца}

End; {окончание описания записи}

Var

M, V : Car; {объявление переменных типа- запись}

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

<тип_поля_...> - любой стандартный тип языка Pascal, включая тип запись, т. е. поле записи может быть в свою очередь записью. Если в качестве <тип_поля_...> используется тип, определенный пользователем, то он должен быть объявлен до описания записи.

Из записей одного типа можно составлять массивы

Пример 2.

Type

Person = Record

FIO : String[20];

Age : Integer;

Prof : String[30];

End;

Var

List : Array[1..50] of Person;

3. Обращение к значению поля осуществляется с помощью составного имени, которое состоит из имени переменной типа запись и идентификатора поля, разделенных точкой. Например, чтобы получить доступ к полям записи Car (см. пример 1), надо написать:

M.Number, M.marka, M.FIO, M.Address.

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

Пример.

а) присваивание полям записи значений в программе (см. пример 1):

M.Number :=1678;

M.Marka :=’ГАЗ-24’;

M.FIO :=’Иванов И. И.’;

M.Address :=’Ул. Пушкина 12-31’;

б) присваивание полям одной записи значений полей другой записи (см. пример):

V:=M;

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

With <переменная_типа_запись>

Do <оператор>;

где <переменная_типа_запись> - имя переменной типа запись, с полями которой нужно работать, <оператор> - простой или составной оператор языка Pascal. Один раз указав имя переменной типа запись в операторе With, можно в пределах этого оператора работать с именами полей как с обычными переменными, т. е. без указания перед идентификатором поля имени переменной, определяющей запись.

Пример.

With M

Do Begin

Number :=1678;

Marka :=’ГАЗ-24’;

FIO :=’Иванов И. И.’;

Address :=’Ул. Пушкина 12-31’;

End;

Примечание. Оператор присоединения действует только на поля записи, указанной в операторе присоединения. Все поля, относящиеся к другой записи, используются только с указанием идентификатора записи.

4. Операции с записями:

  • ввод записи с клавиатуры:

Read(M.Number, M.Marka, M.FIO, M.Address);

  • вывод записи на экран монитора:

Writeln(M.Number:4, M.Marka:7, M.FIO:12, M.Address:25);

  • чтение записи из текстового файла:

Read(<имя_файла>, M.Number, M.Marka, M.FIO, M.Address);

  • вывод значения переменной в текстовый файл:

Writeln(<имя_файла>, M.Number:4, M.Marka:7, M.FIO:12, M.Address:25);

  • сравнение записей:

If M.Fam <> V.Fam

Then …

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

Задача

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

Program Primer;

Uses Crt;

Type

Anketa = Record

Fam, Nm, Ot : String[15];

Born : Integer;

End;

Var

F : File of Anketa;

A : Anketa;

S : Char;

Begin

Assign(F,’Swed.dat’);

Rewrite(F);

Clrscr;

Repeat

With A

Do Begin

Write(‘Фамилия: ’);

Readln(Fam);

Write(‘Имя: ’);

Readln(Nm);

Write(‘Отчество: ’);

Readln(Ot);

Write(‘Год рождения: ’);

Readln(Born);

End;

Write(F, A);

Writeln(‘Продолжить (y/n)’);

Readln(S);

Until Upcase(S)=’N’;

Close(F);

End.

{объявление типа - запись}

{файловая перем. типизированного файла}

{А - запись}

{символьная переменная}

{установление связи между F и Swed.dat}

{открытие файла на запись}

{в цикле}

{для записи А}

{ввод значений полей записи А}

{с клавиатуры}

{запись записи А в файл}

{вывод запроса на продолжение}

{ввод ответа с клавиатуры}

{пока не нажата ‘N’ или ‘ n’}

{закрытие файла}