Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЛР Методы программирования Build1.0.pdf
Скачиваний:
97
Добавлен:
10.06.2015
Размер:
1.89 Mб
Скачать

24

2. Работа с последовательностями, файлы

Вид занятия – лабораторная работа Цель – исследование особенностей последовательного хранения данных

Продолжительность – 4 часа

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

Большинство так называемых усложненных структур: последовательности, деревья, графы и т. д.

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

1.Объем памяти, необходимый для размещения структуры усложненного типа, неизвестен во время трансляции.

2.Объём памяти под данные может изменяться во время выполнения программы.

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

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

Смысл последовательного доступа заключается в том, что в каждый момент доступна лишь одна определённая компонента последовательности. Как следствие из этого:

1.Позиция в последовательности может меняться, определяя лишь следующую компоненту, либо первую компоненту всей последовательности (см. рис. 2.1).

2.Процессы формирования и чтения последовательности не могут выполняться совместно. Поэтому последовательность должна находиться либо в режиме записи либо в режиме чтения.

x = x1, x2 ,...,

 

, xn1, xn

Рисунок 2.1.– Изменение позиции последовательности

Доступ к файлу

Сточки зрения программирования файлы можно классифицировать на:

1.Двоичные (бинарные).

2.Текстовые.

3.Типизированные.

Синтаксис объявления файла в языке Delphi выглядит следующим образом:

var F : File of <тип файла>;

Например:

var

: file;

//двоичный файл

Bin_File

Txt_File

: Textfile;

//текстовый файл

Int_File

: file of Integer;

//файл целых чисел

 

 

 

25

Real_File :

file

of

Real;

//файл вещественных чисел

Record_File :

file

of

TPoint;

//типизированный файл

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

var F : file; begin

AssignFile(F,'C:\MyFile.dat'); //Связывание файловой переменной F с файлом

TRY

//Секция для потенциально опасных операций над файлом

FINALLY

CloseFile(F); //Закрытие файла и освобождение переменной

END; end.

Прокомментирую эти строки. Нами объявлена файловая переменная с именем F. Самая первая процедура, встретившаяся в листинге, предназначена для связывания файловой переменной F с именем файла FileName. Эту процедуру дальше станем называть процедурой инициализации базовых операций ввода-вывода.

procedure AssignFile(var F; FileName: string);

Теперь файловая переменная в состоянии держать связь с эти файлом до тех пор, пока не будет освобождена. Для разрыва связи и освобождения занятых ресурсов необходим вызов процедуры закрытия файла.

procedure CloseFile(var F);

Указанный метод завершает операции ввода-вывода. Обе процедуры всегда применяются в паре, и если в программе был осуществлён вызов AssignFile(), то в заключении позаботьтесь и об обязательном вызове CloseFile(). Однако, при работе с файлом всегда высока вероятность возникновения целого спектра самых разнообразных ошибок, которые могут привести к возникновению исключительной ситуации. Именно по этому в примере процедура закрытия вынесена в секцию finally обработчика ошибки try..finally. Такой подход гарантирует, что даже при возникновении ошибок файловая переменная гарантированно освобождается.

Операции над файлами

Все действия с последовательными файлами можно свести к 4-м операциям.

Первая операция создаёт пустую последовательность. Она реализуется с помощью процедуры:

procedure Rewrite(var F: File [; RecSize: Word ] );

Будьте осторожны! Если файловая переменная F ссылается на файл с данными, то указанный файл будет перезаписан и потеряет всю информацию!

Вторая операция увеличивает последовательность. Благодаря этому последовательность получает приращение на одно значение. На основе данной операции построен механизм записи данных в последовательный файл. Для текстовых файлов:

procedure Writeln([ var F: Text; ] V1 [, V2, ...,Vn ]);

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

procedure Write( [var F: Text; ] P1 [ , P2,..., Pn] );

На этот раз процедура добавит в конец последовательности одно значение. Например, если речь идёт о целочисленном файле, то добавится целое число. Для двоичных файлов подойдёт процедура:

procedure BlockWrite (var f: File; var Buf; Count: Integer);

Второй аргумент Buf служит буфером, в который мы помещаем данные. Третий аргумент Count указывает сколько байт из буфера следует передать в файл.

26

Третья операция применяется в случаях, когда мы планируем считать данные из файла, она называется “инициация просмотра”. На практике для этого потребуются услуги процедуры:

procedure Reset(var F: File; [RecSize: Word ] );

Четвёртая операция позволяет осуществлять переход к следующей компоненте файла. В Delphi, для таких целей применяется процедура:

procedure Seek(var F; N: Longint);

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

На законный вопрос: “А как узнать в каком месте находится указатель в настоящий момент?” нам ответит ещё одна функция:

function FilePos(var F): Longint;

К четвёртой операции с файлами прямое отношение имеет действие, связанное с чтением данных из файла, ведь каждая операция чтения тоже приводит к переходу к очередной компоненте последовательности.

Для чтения целой строки из текстового файла применяем процедуру:

procedure Readln([ var F: Text; ] V1 [, V2, ...,Vn ]);

Для текстовых и типизированных файлов, кроме того, подойдёт процедура:

procedure Read( [ var F: Text; ] V1 [, V2,...,Vn ] );

Она производит чтение порциями, по одному элементу.

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

procedure BlockRead (var F: File; var Buf; Count: Integer);

Параметры процедуры аналогичны параметрам, применяемым в рассмотренной выше BlockWrite(), с той лишь разницей, что сейчас мы читаем данные из файла.

Окончание файла

При просмотре последовательности важно уметь распознавать её окончание, поскольку операция чтения за пределами последовательности приводит к ошибке. Для этой цели воспользуйтесь функцией:

function Eof(var F): Boolean;

В случае если достигнуто окончание файла, функция возвратит значение true, во всех остальных случаях – false.

На законный вопрос: “А как узнать в каком месте находится указатель в настоящий момент?” нам ответит ещё один метод:

function FilePos(var F): Longint;

И если указатель ссылается на начало файла, то функция вернёт нулевое значение, а если на конец, то возвратится значение FileSize (). Этот метод проинформирует программиста о количестве записей в типизированном файле:

function FileSize(var F): Integer;

Чтобы нам не выйти за пределы типизированного файла при его чтении стоит использовать следующую заготовку кода:

while FilePos(F)<>FileSize(F) do begin

Read(F, Буферная_Переменная); //другие операции

end;

27

Пример работы с файлом

Рассмотрите два приёма работы с типизированным файлом. В первом листинге мы создаём файл типизированный типом данных Integer и заполняем его 10 элементами.

program ...; {$APPTYPE CONSOLE} uses SysUtils;

var I : INTEGER; F : File Of INTEGER; begin

AssignFile(F,'C:\int.dat'); {связывание файловой переменной с именем файла} Rewrite(F); //создание файла

TRY

For I:=1 to 10 do

Write(F,I); //внесение значений в файл

FINALLY

CloseFile(F); //закрытие файла

END; end.

Второй листинг демонстрирует процесс чтения из файла данных.

var I : INTEGER; F : File Of INTEGER; begin

AssignFile(F,'C:\int.dat'); {связывание файловой переменной с именем файла} Reset(F); //подготовка файла к чтению

TRY

WHILE EOF(F)<>TRUE do //контролируем окончание файла begin

Read(F,I); //внесение 10 значений в файл

WriteLn(I); //вывод на экран

End;

FINALLY

CloseFile(F); //закрытие файла

END;

ReadLn; end.

Задание

1.Разработайте процедуру, заполняющую файл “A” произвольным количеством случайных вещественных чисел REAL в диапазоне от -100.0 до 100.0.

2.Разработайте процедуру выводящие на экран данные из произвольного файла, типизированного типом данных REAL. Проверьте её работоспособность на файле “A”.

3.Разработайте процедуру, декомпозирующую файл из первого задания следующем образом: целая часть значений передаётся в файл “B”, дробная направляется в файл “С”.

4.Разработайте процедуру, объединяющую целую и дробную части из файлов “B” и “C” (см. задание 3) в файл “D”.

5.Разработайте процедуру, позволяющую вывести содержание файла “A” в обратной последовательности и сохраните полученные данные в файл “E”.

6.Разработайте процедуру, позволяющую конвертировать файл “A” к типизированному файлу следующего вида:

a.поле порядкового номера;

b.поле, хранящее признак отрицательного или положительного значения;

c.поле, содержащее исходное значение по модулю.

Сохраните результат в файле “F”.

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

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