Работа с файлами
Файловые переменные
Под файлом понимается либо именованная область внешней памяти ПК
(жесткого диска, гибкой дискеты, электронного «виртуального» диска), либо
логическое устройство – потенциальный источник или приемник
информации.
Любой файл имеет три характерные особенности. Во-первых, у него
есть имя, что дает возможность программе работать одновременно с не-
сколькими файлами. Во-вторых, он содержит компоненты одного типа.
Типом компонентов может быть любой тип Турбо Паскаля, кроме файлов.
Иными словами, нельзя создать «файл файлов». В-третьих, длина вновь
создаваемого файла никак не оговаривается при его объявлении и ограни-
чивается только емкостью устройств внешней памяти.
Файловый тип или переменную файлового типа можно задать одним из
трех способов:
type
product = record name string;
соde : word;
cost : comp;
end;
105
text80 = file of string[80];
var
f1 : file of char;
f2 : text;
f3 : file;
f4 : text80;
f5 : file of product;
В зависимости от способа объявления можно выделить три вида файлов:
− типизированные файлы (задаются предложением FILE OF...);
− текстовые файлы (определяются типом TEXT);
− нетипизированные файлы (определяются типом FILE).
В наших примерах FI, F4 и F5 - типизированные файлы, F2 -текстовый
файл, F3 - нетипизированный файл. Вид файла, вообще говоря, определяет
способ хранения информации в файле. Однако в Турбо Паскале нет средств
контроля вида ранее созданных файлов. При объявлении уже существующих
файлов программист должен сам следить за соответствием вида объявления
характеру файла.
Любой программе доступны два предварительно объявленных файла со
стандартными файловыми переменными: INPUT - для чтения данных с
клавиатуры и OUTPUT - для вывода на экран. Стандартный Паскаль требует
обязательного упоминания этих файлов в заголовке программы, например,
так
107
За именем диска может указываться имя каталога, содержащего файл.
Если имени каталога предшествует обратная косая черта, то путь к файлу
начинается из корневого каталога, если черты нет - из текущего каталога,
установленного в системе по умолчанию. За именем каталога может
следовать одно или несколько имен каталогов нижнего уровня. Каждому из
них должна предшествовать обратная косая черта. Весь путь к файлу
отделяется от имени файла обратной косой чертой. Максимальная длина
имени вместе с путем - 79 символов, например:
var
finp:text;
fout : file of string;
const
name = ' c:\dir\subdir\out.txt';
assign(finp, '123.dat');
assign(fout, name);
Инициация файла
Инициировать файл означает указать для этого файла направление
передачи данных. В Турбо Паскале можно открыть файл для чтения, для
записи информации, а также для чтения и записи одновременно.
Для чтения файл инициируется с помощью стандартной процедуры
RESET:
108
альная переменная-указатель, связанная с этим файлом, будет указывать на
начало файла, т.е. на компонент с порядковым номером 0.
Если делается попытка инициировать чтение из несуществующего
файла или из логического устройства PRN, возникает ошибка периода
исполнения, которая может быть сообщена программе ненулевым значением
встроенной функции IORESULT типа WORD. Например, следующий
фрагмент программы позволяет установить, существует ли требуемый файл
на диске:
var
f : file of char;
assign(f,'myfile.dat');
{$I-} {Отключить контроль ошибок ввода-вывода}
reset(f):
{SI+} {Включить контроль ошибок ввода-вывода)
If IOResult о 0 then
..... {Файл не существует}
else
..... {Файл существует}
109
запись информации в ранее существовавший дисковый файл: при
выполнении этой процедуры старый файл уничтожается и никаких
сообщений об этом в программу не передается. Новый файл
подготавливается к приему информации и его указатель принимает значение
0.
Стандартная процедура APPEND (<ф.п.>) инициирует запись в ранее
существовавший текстовый файл для его расширения, при этом указатель
файла устанавливается в его конец. Процедура APPEND применима только к
текстовым файлам, т.е. их файловая переменная должна иметь тип TEXT (см.
выше). Процедурой APPEND нельзя инициировать запись в типизированный
или нетипизированный файл. Если текстовый файл ранее уже был открыт с
помощью RESET или REWRITE, использование процедуры APPEND приведет
к закрытию этого файла и открытию его вновь, но уже для добавления
записей.
CLOSE (<ф.п.>)
110
файл можно повторно открыть без дополнительного использования
процедуры ASSIGN.
Процедура RENAME. Переименовывает файл. Формат обращения:
ERASE(<ф.п.>)
var
fi : text; {Исходный файл}
fo : text; {Отредактированный файл}
name : string;
name_bak: string;
k,i : word;
const
bak = '.bak';
........
{ Получить в name_bak имя файла с расширением .ВАК: }
111
k := pos('.',name):
If k=0 then k := length(name) + 1;
name_bak := copy(name,1,k-1) + bak;
{ Проверить существование исходного файла: }
assign(fi,name):
{$I-} reset(fi);
If IOResult о 0 then halt; {Файл не существует}
close(fi):
{ Проверить существование .ВАК-файла: } assign(fo,name_bak);
reset(fo);
{$I+} If IOResult = 0 then
begin {Файл .ВАК существует}
close(fo);
erase(fo);
end;
{ Проверки закончены, подготовка к работе: }
rename(fi,name_bak);
reset(fi);
assign(fo,name);
rewrite(fo);
rename(fi,name_bak);
112
Если операция завершилась успешно, функция возвращает ноль. Коды
ошибочных операций ввода-вывода представлены в прил.З. Следует
помнить, что IORESULT становится доступной только при отключенном
автоконтроле ошибок ввода-вывода. Директива компилятора {$I-} отклю-
чает, а директива {$I+} включает автоконтроль. Если автоконтроль от-
ключен, а операция ввода-вывода привела к возникновению ошибки,
устанавливается флаг ошибки и все последующие обращения к вводу-выводу
блокируются, пока не будет вызвана функция IORESULT.
Ряд полезных файловых процедур и функций становится доступным при
использовании библиотечного модуля DOS.TPU, входящего в стандартную
библиотеку TURBO.TPL . Эти процедуры и функции указаны ниже. Доступ к
ним возможен только после объявления USES DOS в начале программы.
Текстовые файлы
Текстовый файл трактуется в Турбо Паскале как совокупность строк
переменной длины. Доступ к каждой строке возможен лишь последова-
тельно, начиная с первой. При создании текстового файла в конце каждой
записи (строки) ставится специальный признак EOLN (End Of LiNe -конец
строки). а в конце всего файла - признак EOF (End Of File - конец файла).
Для доступа к записям применяются процедуры READ, READLN,
WRITE, WRITELN. Они отличаются возможностью обращения к ним с
переменным числом фактических параметров, в качестве которых могут
использоваться символы, строки и числа. Первым параметром в любой из
перечисленных процедур может стоять файловая переменная. В этом случае
осуществляется обращение к дисковому файлу или логическому устройству,
связанному с переменной процедурой ASSIGN. Если файловая переменная
не указана, происходит обращение к стандартным файлам Input и Output.
Процедура READ. Обеспечивает ввод символов, строки чисел. Формат
обращения:
READ (<ф.п.>,<сп.ввода>);
113
или
READ (<сп.ввода>);
const
N = 1000; { максимальная длина ввода }
var
f : text;
m : array [1..N] of real;
i : Integer;
BEGIN
assign(f, 'prog.dat');
reset(f);
i := 1;
while not EOF(f) and (I <= N) do
begin
read(f,m[i]);
inc(i);
end;
сlоse(f);
end.
114
Процедура READLN. Обеспечивает ввод символов, строк и чисел. Эта
процедура идентична процедуре READ за исключением того, что после
считывания последней переменной оставшаяся часть строки до маркера
EOLN пропускается, поэтому следующее обращение к READLN или READ
начинается с первого символа новой строки. Кроме того, эту процедуру
можно вызвать без параметра <сп.ввода> (см. процедуру READ), что
приведет к пропуску всех символов текущей строки вплоть до EOLN.
Процедура WRITE. Обеспечивает вывод информации в текстовый файл
или передачу ее на логическое устройство. Формат обращения:
115
если - большую длину, то подпараметр MINWIDTH итерируется и выводится
необходимое число символов.
Подпараметр DECPLACES задает количество десятичных знаков в
дробной части вещественного числа. Он может использоваться только
совместно с MINWIDTH и только по отношению к выводимому выражению
одного из вещественных типов.
Если ширина поля вывода не указана, соответствующий параметр
выводится вслед за предыдущим без какого-либо их разделения.
Процедура WRITELN. Эта процедура полностью идентична процедуре
WRITE за исключением того, что выводимая строка символов завершается
кодами CR и LF. При вызове WRITELN можно опускать параметр
<сп.вывода>: в этом случае в файл передается маркер EOLN, что при выводе
на экран приведет к переводу курсора в начало следующей строки.
Логическая функция EOLN. Возвращает TRUE, если во входном
текстовом файле достигнут маркер конца строки. Формат обращения:
EOLN(<ф.n.>);
var
f: text;
s: string;
const
Sum: longint = 0; {Здесь будет количество символов}
BEGIN
Writе('Имя файла: '); {Запросить}
116
Readln(s); {и ввести имя файла}
assign(f ,s);
Reset(f); {Открыть файл}
while not EOF(f) do {Подсчитать}
begin {количество}
Readln(f,s); {символов}
inc(Sum, Length(s)) {в тексте}
end; {этой программы}
Close(f); {Закрыть файл}
Writeln('Объем - ',Sum/40000:6:2,' уч.изд.л.');
END.
Типизированные файлы
Длина любого компонента типизированного файла строго постоянна,
что дает возможность организовать прямой доступ к каждому из них (т.е.
доступ к компоненту по его порядковому номеру).
Перед первым обращением к процедурам ввода-вывода указатель файла
стоит в его начале и указывает на первый компонент с номером 0. После
каждого чтения или записи указатель сдвигается к следующему компоненту
файла. Переменные в списках ввода-вывода должны иметь тот же тип, что и
компоненты файла. Если этих переменных в списке несколько, указатель
будет смещаться после каждой операции обмена данными между
переменными и дисковым файлом.
Процедура READ. Обеспечивает чтение очередных компонентов
типизированного файла. Формат обращения:
READ (<ф.п.>,<сп.ввода>);
WRITE (<ф.п.>,<сп.вывода>);
FILESIZE(<ф.п.>);
seek(FileVar, FileSize(FileVar));
118
FILEPOS(<ф.п.>);
Нетипизированные файлы
Нетипизированные файлы объявляются как файловые переменные типа
FILE и отличаются тем, что для них не указан тип компонентов. Отсутствие
типа делает эти файлы, с одной стороны, совместимыми с любыми другими
файлами, а с другой - позволяет организовать высокоскоростной обмен
данными между диском и памятью.
При инициации нетипизированного файла процедурами RESET или
REWRITE можно указать длину записи нетипизированного файла в байтах.
Например, так:
var
f : file;
..........
assign(f, 'myfile.dat');
reset(f,5l2);
119
BLOCKREAD(<ф.п.>,<буф>,<N>[,<NN>]);
BLOCKWRITE(<ф.п.>,<буф>,<N>[,<NN>]);
Определение множеств
Множества – это наборы однотипных логически связанных друг с
другом объектов. Характер связей между объектами лишь подразумевается
программистом и никак не контролируется Турбо Паскалем. Количество
элементов, входящих в множество, может меняться от 0 до 256 (множество,
120
не содержащее элементов, называется пустым). Именно непостоянством
количества своих элементов множества отличаются от массивов и записей.
Два множества считаются эквивалентными тогда и только тогда, когда
все их элементы одинаковы, причем порядок следования элементов в
множестве безразличен. Если все элементы одного множества входят также и
в другое, говорят о включении первого множества во второе. Пустое
множество включается в любое другое.
Пример определения и задания множеств:
type
DigitChar = set of '0'..'9';
Digit = set of 0..9;
var
s1,s2,s3: DigitChar;
s4,s5,s6: Digit;
...
s1:=['1','2','3'];
s2:=['3','2','1'];
s1:=['2','3'];
s1:=[0..3,6];
s1:=[4,5];
s1:=[3..9];
...
121
Для задания множества используется так называемый конструктор
множества: список спецификаций элементов множества, отделяемых друг от
друга запятыми; список обрамляется квадратными скобками.
Спецификациями элементов могут быть константы или выражения базового
типа, а также – тип-диапазон того же базового типа.
122
2*2 in s1 возвращает false;
Пример
В следующем примере реализуется алгоритм выделения из первой сотни
натуральных чисел всех простых. В его основе (также как и в примере из
лабораторной работы №3) лежит прием, известный под названием «решето
Эратосфена». Сравните программы, приведенные здесь и в лабораторной
работе №3.
{ Вывод результата: }
for i := 1 to N do
if I in PrimerSet then write(i:8);
writeln;
END.
124