Смекни!
smekni.com

Алгоритмический язык Паскаль (стр. 13 из 31)

F
^
окно

1. READ(F,V) - переменной V присваивается значение текущей позиции файла F, и окно перемещается на следующую позицию.

F F1 F2 F3 F4 ® F F1 F2 F3 F4
^ ^
окно окно

ПРИМЕЧАНИЕ. Файл открывается либо только для записи, либо для чтения - одновременно это делать нельзя!!!

1. При работе с файлами необходимо знать конец файла. Это делает логическая функция EOF:

EOF(F) = FАLSE, если конец файла не достигнут;

EOF(F) = TRUE - признак конца файла.

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

ПРИМЕР 1. Расшифровка текста

Пусть все буквы от A до Z имеют коды от 65 до 90. Имеется файл SHIFRTEXT, состоящий из чисел от 65 до 90. Напечатать расшифрованный текст:

program RASSHIFROVKA (SHFRTXT);¦ program KODIROVKA;

type KOD = 65..90; ¦ type KOD = 65..90;

LITERA = 'A'..'Z'; ¦ SHIFR = file of KOD;

SHIFR = file of KOD; ¦ var x: KOD;

var x: KOD; ¦ SH: SHIFR;

y: LITERA; ¦ begin

SH: SHIFR; ¦ ¦ assign(SH,'shfrtxt');

begin ¦ ¦ rewrite (SH);

¦ assign(sh,'shfrtxt'); ¦ ¦ read(x);

¦ reset(SH); ¦ ¦ while x<> 00 do begin

¦ while not eof(SH) do¦ ¦ ¦ write (SH,x);

¦begin ¦ ¦ ¦

¦ ¦ read(SH,x); ¦ ¦ ¦ read(x);

¦ ¦ y:=chr(x); ¦ ¦ end;

¦ ¦ write(y); ¦ ¦ close(SH);

¦ end; close(sh); ¦ end.

end.

ПОЯСНЕНИЕ. В рассмотренном примере программа RASSHIFROVKA производит расшифровку строки числовых кодов файла SHFRTXT, сформированного с помощью программы KODIROVKA. В программе KODIROVKA предусмотрен непрерывный ввод кодов - двухзначных чисел от 65 до 90, разделяемых пробелом. Признаком конца ввода является код 00.

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

10.3 Буферная переменная

Мы знаем, что для чтения компоненты файла используется процедура READ(F,V). По этой процедуре выполняются два действия:

1. Копирование компоненты файла F, на которую смотрит окно, и присваивание этого значения переменной V.

2. Перемещение окна на следующую компоненту.

Однако, иногда удобно эти два действия разделить. Для этого вводится понятие буферной переменной. Она имеет имя: F^. Эту переменную не надо описывать, она определяется автоматически, как только описывается файл F. Тип F^ совпадает с типом компоненты файла. С переменной F^ можно выполнять все действия, как над данными типа компонент файла.

Если выполнена процедура RESET(F), то происходит установка окна на первую компоненту и значение этой компоненты идет в F^:

F X F^
^
окно

Если выполнен RESET(F), а файл F пуст, т.е. EOF(F)=TRUE, то значение F^ неопределенно. Окно файла указывает на его конец. Для передвижения окна файла и заполнения (чтения) буферной переменной используются в некоторых версиях Паскаля специальные процедуры-операторы GET и PUT:

а) GET(F) - передвижение окна на следующую компоненту и засылка значения этой компоненты в переменную F^.

F^ 7 f 3 5 7 8
^
окно

после GET(F):

F^ 8 f 3 5 7 8
^
окно

б) PUT(F) - запись в файл значения F^ и сдвиг вправо. Здесь до PUT(F) надо F^ присвоить очередное значение. В режиме записи значений в файл F^ служит поставщиком значений компонент. После процедуры REWRITE(F) окно устанавливается на первую компоненту, значение F^ не определено. Затем надо определить значение F^ с помощью команды присваивания: F^:=3. Если теперь написать процедуру PUT(F), то значение F^ идет в компоненту, где стоит окно, после чего значение F^ становится неопределенным:

F^ 3 f 6 4 7 8
^
окно

PUT(F)

F^ f 6 4 7 8 3
^
окно

ПРИМЕР 2. Запись чисел v1 - v5 в файл BUFFER и последующий их вывод на печать

program KVADRKOREN;

var R: real; I: integer; BUFFER: file of real;

begin

¦ rewrite(BUFFER);

¦ for I:=1 to 5 do

¦ begin

¦ ¦ BUFFER^:=sqrt(I); put(BUFFER);

¦ end;

¦ reset(BUFFER);

¦ for I:=1 to 5 do

¦ begin

¦ ¦ R:=BUFFER^;

¦ ¦ get(BUFFER); writeln(R);

¦ end;

end.

ЗАМЕЧАНИЕ. В некоторых версиях процедуры GET и PUT не существуют (в частности, это имеет место для Турбо-Паскаля). Но без них можно обойтись, т.к. существуют эквивалентные им операторы READ и WRITE. Им эквивалентны следующие составные операторы:

READ(F,V) => BEGIN V:=F^; GET(F) END;

WRITE(S,W) => BEGIN S^:=W; PUT(S) END.


10.4 Основные приемы работы с файлами

Известно существование многих версий Паскаля, каждая из которых имеет свои особенности и отличия от стандарта Паскаля. Рассмотрим некоторые приемы работы с файлами в системах Turbo-Pascal для ПЭВМ "Ямаха" и IBM PC.

Перед началом работы с файлами (до первого обращения к файлу) должна быть выполнена процедура ASSIGN. Эта процедура отождествляет имя файла с соответствующей файловой переменной.

СИНТАКСИС: assign(var F: file; NAME: string), где NAME - имя файла на диске, F - имя файловой переменной.

После выполнения этой процедуры NAME и F отождествляются, например, ASSIGN(F,'nomfile') отождествляет файловую переменную F с его именем на диске. В качестве имени файла может быть указаноего полное имя, т.е. путь к этому файлу, например:

ASSIGN(F,'С:&bsol;WORK&bsol; MIM&bsol;nomfile').

После окончания работы с файлом он должен быть закрыт процедурой CLOSE, иначе результат может быть потерян, т.к. директория не будет обновлена.

СИНТАКСИС: CLOSE(var F:file), где F - имя файловой переменной.

Процедуры ASSIGN и CLOSE взаимосвязаны и работают в паре друг с другом. Как уже сказано выше, перед началом работы с файлом выполняется процедура ASSIGN(F, 'nomfile'), которая для логического файла F готовит (ищет) на диске в указанной директории файл с именем NOMFILE. При окончании работы с файлом по выполнению процедуры CLOSE происходит его обновление (в случае записи) и закрытие (в случае чтения).

В программе надо уметь задавать исходные файлы. Эти файлы надо делать в цикле, используя при этом формирование компонент, либо в форме некоторого выражения по RANDOMIZE, либо задействовать обычную команду READ для ввода данных с клавиатуры. Цикл можно делать FOR, если формирование файла идет по RANDOMIZE, или WHILE (REPEAT), если файл формируется по признаку конца ввода.

Напомним, что RANDOMIZE - процедура инициализации генератора случайных величин; RANDOM - функция генерации случайных чисел.

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

ПРИМЕР 2. Для двух целочисленных файлов F и G одинаковой длины образовать третий целочисленный файл H, компоненты которого определяются по правилу: Hi=MAX{Fi,Gi}. В программе предусмотреть вывод на экран все трех файлов

program MAXELEM;

type FT = file of integer;

var F,G,H: FT;

I,J: integer;

procedure VIVODFILE(var A:FT);

begin

¦ reset(A);

¦ while not eof(A) do

¦ begin

¦ read(A,I); write(I:4);

¦ end; writeln;

end;

begin { формирование исходных файлов }

¦ assign(F,'F'); assign(G,'G');

¦ randomize; rewrite(F); rewrite(G);

¦ for I:=1 to 10 do

¦ begin

¦ J:= random(10)-5; write(F,J);

¦ ¦ J:= random(10)-5; write(G,J);

¦ end;

¦ VIVODFILE(F); close(F);

¦ VIVODFILE(G); close(G);

¦ assign(H,'H');

¦ { формирование файла результата }

¦ reset(F); reset(G); rewrite(H);

¦ while not eof(F) do

¦ begin

¦ ¦ read(F,I); read(G,J);

¦ ¦ if I > J then write(H,I) else write(H,J);

¦ end; VIVODFILE(H);

¦ close(H);

end.

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

procedure DOBAVLENIE(N: integer; var A:file);

var B: file; I,J: integer;

begin

¦ { Запись файла А в файл B }

¦ assign(B,'B');reset(A; rewrite(B);

¦ while not eof(A) do

¦ begin read(A,I); write(B,I); end;

¦ { Добавление новых элементов в файл B }

¦ for I:=1 to n do

¦ begin

¦ J:= random(10)-5; write(B,J);

¦ end;

¦ { Запись файла B в файл A }

¦ rewrite(A); reset(B);

¦ while not eof(B) do

¦ begin read(B,I); write(A,I); end;

end.

10.5 Текстовые файлы

Среди всех файлов особое место занимают текстовые файлы. Особенностью текстовых файлов является объединение в них символов в строки. Каждая строка кончается специальным символом конца строки. Этот специальный символ (литера) не входит в стандартный тип CHAR и не имеет графического представления. Нас и не интересует вид этого символа. Главное, что с ним связана логическая функция EOLN (конец строки). EOLN(F) = TRUE, если окно указывает на признак конца строки. Заметим, что если EOLN(F) = TRUE, то при чтении элементов из файла в символьную переменную она принимает значение пробела (пробел - аналог конца строки). Для записи в файл признака конца строки служит стандартная процедура WRITELN.

Текстовые файлы, т.е. файлы с делением на строки, описываются с помощью слова TEXT, например, VAR X, D: TEXT.

ПРИМЕР 3. Определить количество строк в файле с именем BOOK

program NOMBRELINE;

var K: integer; BOOK: text; S: char;

begin { Формированиефайла BOOK }

¦ assign(BOOK,'f1'); rewrite(BOOK); read(S);

while S<> '.' do begin

¦ while S <> '#' do begin

¦ write(BOOK,S); read(S); end;

¦ writeln(book);read(S); end; close(BOOK);

¦ { Подсчет числа строк в текст; BOOK }

¦ K:= 0; reset(BOOK); writeln;

¦ while not eof(BOOK) do

¦ begin

¦ if eoln(BOOK) then K:=K+1; read(BOOK,S); write(S);

¦ end;

¦ writeln('В текстовом файле BOOK ', K,' - строк');

end.

ПОЯСНЕНИЕ. В программе сначала формируется текстовый файл, у которого строки кончаются символом "$", а сам текст – символом ".". Текст вводится с клавиатуры в виде непрерывной цепочки, например: