Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Учебное пособие 1159

.pdf
Скачиваний:
4
Добавлен:
30.04.2022
Размер:
823.79 Кб
Скачать

var V2 : ... ; end {S};

var V3 : . . .;

Из процедуры S можно обратиться к переменным VI и V2, но нельзя использовать V3, так как описание V3 следует в программе за описанием процедуры S.

Локализованные в подпрограмме имена могут совпадать с ранее объявленными глобальными именами. В этом случае считается, что локальное имя «закрывает» глобальное и делает его недоступным. Таким образом, одноименные глобальные и локальные переменные - это разные переменные. Любое обращение к таким переменным в теле подпрограммы трактуется как обращение к локальным переменным, т. е. глобальные переменные в этом случае попросту недоступны.

7.2 Описание подпрограммы Описание подпрограммы состоит из заголовка и тела

подпрограммы.

Заголовок процедуры имеет вид:

PROCEDURE <имя> [(<сп.ф.п.>)];

Заголовок функции:

FUNCTION <имя> [(<сп.ф.п.>)] : <тип>;

Здесь <имя> - имя подпрограммы (правильный идентификатор); <сп.ф.п> - список формальных параметров; <тип> - тип возвращаемого функцией результата.

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

Procedure SB (a: Real; b: Integer; c: Char);

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

Рассмотрим такой полезный пример. В Object Pascal не

59

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

X Y = e ( Y * ln (X) )

Создадим функцию с именем Power и двумя вещественными параметрами А и В, которая будет возвращать результат возведения А в сте пень В. Обработчик события bbRunCUck нашей учебной формы fmExample читает из компонента edinput текст и пытается выделить из него два числа, разделенных хотя бы одним пробелом. Если это удалось сделать, он обращается к функции power дважды: сначала возводит первое число А в степень второго числа У, затем X возводится в степень -У.

procedure TfmExample.bbRunClick(Sender: TObject); Function Power(A, B: Real): Real;

{ Функция возводит число А в степень В. Поскольку логарифм отрицательного числа не существует, реализуется проверка значения А: отрицательное значение заменяется на положительное, для нулевого числа результат равен нулю. Кроме того, любое число в нулевой степени дает единицу.}

begin

if А > 0 then

Result := Ехр(В * Ln(A)) else if A < 0 then

Result := Exp(B * Ln(Abs(A))) else if B = 0 then

Result :=1

 

else Result := 0;

 

end;

// Power

var

 

S: String;

 

X, Y: Real;

 

begin

 

{ Читаем строку из edinput 'и выделяем из нее два веще-

60

ственных числа, разделенных хотя бы одним пробелом } .

.

S := edinput.Text;

 

 

if (S = ' ') or (pos ' ' ,S) = 0)

then Exit;

 

// Нет текста или в нем нет

пробела –

//прекращаем дальнейшую работу try // Выделяем первое число:

Х := StrToFloat(copy(S, 1, pos(' ', S) - 1));

//Если успешно, удаляем символы до пробела и выделяем второе число:

Delete (S, I, pos(' ', S));

Y := StrToFloat(Trim(S)); except

Exit; // Завершаем работу при ошибке преобразования end;

mmOutput.Lines.Add(FloatToStr(Power(X, Y))) ; mmOutput.Lines.Add(FloatToStr(Power(X, -Y)));

end;

Для вызова функции Power мы просто указали ее в качестве параметра при обращении к стандартной функции преобразования веществен ного числа в строку FloatToStr. Параметры Х и У в момент обращения к функции Power - это фактические параметры. Они подставляются вместо формальных параметров А и В в заголовке функции и затем над ними осуществляются нужные действия. Полученный результат присваивается специальной переменной с именем Result, которая в теле любоq функции интерпретируется как то значение, которое вернет функция после окончания своей работы. В программе функция Power вызываетеся дважды - сначала с параметрами Х и У, а затем Х и -У, поэтому буду получены два разных результата.

7.3 Формальные и фактические параметры Механизм замены формальных параметров на фактиче-

ские позволяет нужным образом настроить алгоритм, реализованный в подпрограмме. Object Pascal следит за тем, чтобы ко-

личество и типы формальных параметров строго соответство-

61

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

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

В предыдущем примере параметры А и В определены как параметры-значения., Если параметры определяются как пара- метры-переменные, перед ними необходимо ставить зарезервированное слово var, а если это параметры-константы - слово const, например:

Procedure MyProcedure(var A: Real; B: Real; const C: String);

Здесь А - параметр-переменная, В - параметр-значение, а С- параметр-константа.

Определение формального параметра тем или иным способом существенно, в основном, только для вызывающей программы: если формальный параметр объявлен как параметрпеременная, то при вызове |подпрограммы ему должен соответствовать фактический параметр в виде переменной нужного типа; если формальный параметр объявлен как параметрзначение или параметр-константа, то при вызове ему может соответствовать произвольное выражение. Контроль за неукоснительным соблюдением этого правила осуществляется компилятором. Если бы для предыдущего примера был использован такой заголовок функции:

Function Power (A: Real; var В : Real): Real;

то при втором обращении к функции компилятор указал бы на несоответствие типа фактических и формальных параметров (параметр обращения -Y есть выражение, в то время как соответствующий ему формальный параметр В описан как пара- метр-переменная). 62

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

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

Если параметр определен как параметр-переменная, то при вызове подпрограммы передается сама переменная, а не ее копия (фактически при этом случае подпрограмме передается адрес переменной). Изменение параметра-переменной приводит к изменению фактического параметра в вызывающей программе.

В случае параметра-константы в подпрограмму также передается адрес области памяти, в которой располагается переменная или вычисленное значение. Однако компилятор блокирует любые присваивания параметру-константе нового значения в теле подпрограммы.

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

стиля программирования рекомендуется там, где это возмож-

63

но, использовать передачу результатов через фактические па- раметры-переменные.

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

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

8 Файлы и работа с ними

8.1 Понятие файла Под файлом понимается именованная область внешней

памяти ПК (жесткого диска, дискеты, диска CD-ROM).

Любой файл имеет три характерные особенности. Вопервых, у него есть имя, что дает возможность программе работать одновременно с несколькими файлами. Во-вторых, он содержит компоненты одного типа. Типом компонентов может быть любой тип Object Pascal, кроме файлов. Иными словами, нельзя создать "файл файлов". В-третьих, длина вновь создаваемого файла никак не оговаривается при его объявлении и ограничивается только емкостью устройств внешней памяти.

Файловый тип или переменную файлового типа можно задать в разделе описаний var одним из трех способов:

<имя> = File of <тип>; <имя> = TextFile; <имя> = File;

Здесь <имя> - имя файлового типа (правильный идентификатор); File, of - зарезервированные слова (файл, из); TextFile - имя стандартного типа текстовых файлов; <тип> - любой тип Object Pascal, кроме файлов.

В зависимости от способа объявления можно выделить три вида файлов:

типизированные файлы (задаются предложением File of...);

текстовые файлы (определяются типом TextFile);

нетипизированные файлы (определяются типом File).

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

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

Файловая переменная связывается с именем файла в результате обращения к стандартной процедуре:

AssignFile (<ф.п.>, <имя файла>);

Здесь <ф.п.> - файловая переменная (правильный идентификатор, объявленный в программе как переменная файлового типа); <имя файла> - текстовое выражение, содержащее имя файла.

Инициировать файл означает указать для этого файла направление передачи данных. В Object Pascal можно открыть файл для чтения, для записи информации, а также для чтения и записи одновременно.

Для чтения файл инициируется с помощью стандартной процедурыt:

Reset (<ф.п.>);

Здесь <ф.п.> - файловая переменная, связанная ранее процедурой AssignFile с уже существующим файлом.

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

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

var

F : File; IsFile: Boolean; begin

AssignFile(f,'my file.dat'); try

Reset(F); IsFile:= True;

except

IsFile:= False; end;

if IsFile then

65

66

 

..... // Файл существует else

..... // Файл не существует end;

Вэтом фрагменте с помощью блока try... except...

end реализуется защита программы от краха в случае, если делается попытка открыть несуществующий файл. В случае отсутствия файла при выполнении оператора Reset(F) нормальное выполнение программы прервется и управление будет передано в секцию except...end обработки исключения, в которой переменной IsFile будет присвоено значение False. Если файл существует, исключение не возникнет и переменная IsFile получит значение True.

ВObject Pascal разрешается обращаться к типизированным файлам, открытым процедурой Reset (т.е. для чтения информации), с помощью процедуры Write (т.е. для записи информации). Такая возможность позволяет обновлять ранее созданные типизированные файлы и при необходимости расши-

рять их. Для текстовых файлов, открытых процедурой

Reset, нельзя использовать процедуру Write или WriteLn (см. далее).

Стандартная процедура Rewrite (<ф.п.>); иниции-

рует запись информации в файл, связанный с файловой переменной <ф.п.>. Процедурой Rewrite нельзя инициировать запись информации в ранее существовавший дисковый файл: при выполнении этой процедуры старый файл (если он был) уничтожается и никаких сообщений об этом в программу не передается. Новый файл подготавливается к приему информации и его указатель принимает значение 0.

Стандартная процедура Append (<ф.п.>); инициирует запись в ранее существовавший34 текстовый файл для его расширения, при этом указатель файла устанавливается в его конец. Процедура Append применима только к текстовым файлам, т.е. их файловая переменная должна иметь тип TextFile. Процедурой Append нельзя инициировать запись в типизированный или нетипизйрованный файл. Если текстовый файл ра-

67

нее уже был открыт с помощью Reset или Rewrite, использование процедуры Append приведет к закрытию этого файла и открытию его вновь, но уже для добавления записей.

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

 

Таблица 8

Function AssignFile

Связывает файловую переменную F с

(var F; FileName:

именем файла FileName.

String);

 

Function

Изменяет текущий каталог: Path - строко-

ChDir(Path: String);

вое выражение, содержащее путь к уста-

 

навливаемому по умолчанию каталогу.

Function CloseFile

Закрывает файл, однако связь файловой

(var F);

переменной F с именем файла, установ-

 

ленная ранее процедурой AssignFile, со-

 

храняется. При создании нового или

 

расширении старого файла процедура

 

обеспечивает сохранение в файле всех

 

новых записей и регистрацию файла в

 

каталоге. Функции процедуры CloseFile

 

выполняются автоматически по отноше-

 

нию ко всем открытым файлам при нор-

 

мальном завершении программы. По-

 

скольку связь файла с файловой пере-

 

менной сохраняется, файл можно по-

 

вторно открыть без дополнительного ис-

 

пользования процедуры AssignFile.

Function DiskFree

Возвращает объем в байтах свободного

(D: Byte): Longint;

пространства на указанном диске: D -

 

номер диска (0 - устройство по умолча-

 

нию, 1 - диск А , 2 - диск В и т.д.). Функ-

 

ция возвращает значение -1, если указан

 

номер несуществующего диска.

Function DiskSpace

Возвращает объем в байтах полного про-

68

(D: Byte): Longint;

странства на указанном диске (аналогич-

 

но DiskFree)

 

 

Function EOF

Тестирует конец файла и возвращает

(var F): Boolean;

True, если файловый указатель стоит в

 

конце файла. При записи это означает,

 

что очередной компонент будет добавлен

 

в конец файла, при чтении - что файл ис-

 

черпан.

 

 

Function Erase

Уничтожает файл F. Перед выполнением

(var F);

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

Function FileExists

Проверяет существование файла с име-

(const FileName:

нем (и, возможно, маршрутом доступа)

string): Boolean;

FileName и возвращает True, если файл

 

существует.

 

 

Function FindClose

Освобождает память, выделенную для

(var F: TsearchRec);

поиска

файлов

функциями

 

FindFirst/FindNext.

 

Function FindFirst

Возвращает атрибуты первого из файлов,

(const Path: String;

зарегистрированных в указанном катало-

Attr: Integer; var F:

ге: Path - маршрут поиска и маска выбора

TSearchRec): Integ-

файлов; Attr - атрибуты выбираемых

er;

файлов; F - переменная типа TSearchRec,

 

в которой будет возвращено имя первого

 

выбранного файла.

 

Function FindNext

Возвращает в переменой F имя следую-

(var F: TsearchRec):

щего файла в каталоге. Переменная F

Integer;

должна предварительно инициироваться

 

обращением к функции FindFirst.

Function Flush

Очищает внутренний буфер файла и, та-

(var F);

ким образом, гарантирует сохранность

 

всех последних изменений файла на дис-

 

ке.

 

 

Function GetDir(D: Возвращает имя текущего каталога (каByte; var S: Strings; талога по умолчанию): D - номер устройства (см. выше); S - переменная типа

 

String, в которой возвращается путь к те-

 

кущему каталогу на указанном диске.

Function IOResult:

Возвращает условный признак последней

Integer;

операции ввода-вывода.

Function MkDir

Создает новый каталог на указанном

(Dir: String);

диске: Dir маршрут поиска каталога. По-

 

следним именем в маршруте, т.е. именем

 

вновь создаваемого каталога не может

 

быть имя уже существующего каталога.

Function Rename

Переименовывает файл F; NewName -

(var F; NewName:

строковое выражение, содержащее новое

String);

имя файла. Перед выполнением процеду-

 

ры необходимо закрыть файл

Function Reset

Открывает существующий файл. RecSize

(var F: File

имеет смысл только для нетипизирован-

[; RecSize: Word]);

ных файлов и указывает размер блока

 

данных.

Function Rewrite

Создает новый файл. RecSize имеет

(var F: File

смысл только для нетипизированных

[; Recsize: Word]);

файлов и указывает размер блока данных.

Function RmDir

Удаляет каталог Dir. Удаляемый каталог

(Dir: String);

должен быть пустым, т.е. не содержать

 

файлов или имен каталогов нижнего

 

уровня.

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

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

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

69

Текстовый файл трактуется в Object Pascal как совокупность строк переменной длины. Доступ к каждой строке возможен лишь последовательно, начиная с первой. При создании текстового файла в конце каждой строки ставится специальный признак EOLN (End Of LiNe - конец строки), а в конце всего файла - признак EOF (End70 Of File - конец файла). Эти признаки можно протестировать одноименными логическими функциями. При формировании текстовых файлов используются следующие системные соглашения:

EOLN - последовательность кодов #13 (CR) и #10 (LF);

EOF - код #26.

Для доступа к записям применяются процедуры Read, ReadLn, Write, WriteLn. Они отличаются возможностью обращения к ним с переменным числом фактических параметров, в качестве которых могут использоваться символы, строки и числа. Первым параметром в любой из перечисленных процедур должна стоять файловая переменная. Обращение осуществляется к дисковому файлу, связанному с переменной F проце-

дурой AssignFile (табл.9).

 

 

 

Таблица 9

 

 

 

 

Function Eoln(var F:

Тестирует

маркер конца

строки и воз-

TextFile): Boolean;

вращает True, если конец строки достиг-

 

нут.

 

 

Function Read

Читает из текстового файла последова-

(var F: TextFile; V1

тельность

символьных

представлений

[, V2, . . . ,Vn ] );

переменных Vi типа Char, Siring, а также

 

любого целого или вещественного типа

 

игнорируя признаки EOLN.

Function ReadLn

Читает из текстового файла последова-

(var F: TextFile;

тельность

символьных

представлений

[VI [, V2, ..., Vn]]);

переменных Vi типа Char, String, а также

 

любого целого или вещественного типа с

 

учетом границ строк.

 

Function SeekEof

Пропускает все пробелы,

знаки табуля-

(var F: Text): Boo-

ции и маркеры конца строки EOLN до

lean;

маркера конца файла EOF или до первого

 

значащего символа и возвращает True,

 

если маркер EOF обнаружен.

Function SeekEoln

Пропускает все пробелы и знаки табуля-

(var F: TextFile):

ции до маркера конца строки EOLN или

Boolean;

до первого71 значащего символа и возвра-

 

щает True, если маркер обнаружен.

Function Write

Записывает

символьные

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

(var F: Text; PI

переменных Vi, в текстовый файл.

[, P2, ..., Pn]);

 

 

 

Function WriteLn

Записывает

символьные

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

(var F: Text;

переменных Vi и признак конца строки

[PI [, P2, .... Pn]]);

EOLN в текстовый файл.

 

Процедура Read предназначена для последовательного чтения из текстового файла символьных представлений переменных Vi. При чтении переменных типа Char выполняется чтение одного символа и присваивание считанного значения переменной. Если перед выполнением чтения указатель файла достиг конца очередной строки, то результатом чтения будет символ CR (код #13), а если достигнут конец файла, то - символ EOF (код #26). Процедуру Read не рекомендуется использовать для ввода переменных типа String, т.к. она не способна "перепрыгнуть" через разделитель строк EOLN и читает только первую строку текстового файла. Для ввода последовательности строк нужно использовать процедуру ReadLn.

При вводе числовых переменных процедура Read вначале выделяет подстроку во входном потоке по следующему правилу: все ведущие пробелы, символы табуляции и маркеры конца строк EOLN пропускаются; после выделения первого значащего символа, наоборот, любой из перечисленных символов или символ EOF служат признаком конца подстроки. Выделенная таким образом подстрока затем рассматривается как символьное представление числовой константы соответствующего типа и преобразуется во внутреннее представление, а полученное

значение присваивается переменной. Если в подстроке был нарушен требуемый формат представления численной константы, возникает исключительная ситуация. Если при пропуске ведущих пробелов встретился символ EOF, переменная получает значение 0. В Object Pascal не предусмотрен ввод шестнадцатеричных констант.

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

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

Процедура Write обеспечивает вывод в текстовый файл группы переменных. Любой элемент списка вывода может иметь форму

OutExpr [ : MinWidth [ : DecPlaces ] ]

Здесь OutExpr - выводимое выражение; MinWidth, DecPlaces - выражения типа Integer (квадратные скобки означают возможность отсутствия заключенных в них параметров). Параметр MinWidth, если он присутствует, указывает минимальную ширину поля, в которое будет записываться символьное представление значения OutExpr. Если символьное представление имеет меньшую длину, чем MinWidth, оно будет дополнено слева пробелами, если большую длину, то MinWidth игнорируется и в файл помещается необходимое число символов. Параметр DecPlaces задает количество десятичных знаков в дробной части вещественного числа. Он может использо-

ваться только совместно с MinWidth и только по отношению к выводимому выражению одного из вещественных типов.

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

вывода.

73

 

При выводе логических выражений в зависимости от их

значения выводятся слова True или False. (Ввод логических констант процедурами Read или ReadLn не предусмотрен).

Вещественные числа выводятся в экспоненциальном формате, если не указан параметр DecPlaces, в противном случае выбирается формат представления числа с фиксированной точкой. Если подпараметр MinWidth опущен, принимается его значение по умолчанию (23). Если MinWidth меньше 10, считается, что он равен 10. Если подпараметр DecPlaces равен нулю, ни дробная часть числа, ни десятичная точка не выводятся. При отрицательном значении DecPlaces этот параметр игнорируется и число выводится в экспоненциальном формате с учетом MinWidth. Если значение DecPlaces больше 18, принимается значение 18. Следует учесть, что при указании подпараметра DecPlaces вещественное число всегда будет выводиться в формате с фиксированной точкой и требуемым коли чеством знаков в дробной части, даже если значение подпара-

метра MinWidth окажется недостаточным для размещения целой части: в этом случае значение MinWidth автоматически увеличивается.

Процедура WriteLn полностью идентична процедуре Write за исключением того, что выводимая последовательность символов автоматически завершается маркером EOLN (свое название процедура получила от Write Line - писать строку). При вызове WriteLn можно опускать параметры Vi - в этом случае в файл передается пустая строка.

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

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

Перед первым обращением к процедурам ввода-вывода

указатель файла стоит в его начале и указывает на первый

74

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

Подпрограммы для работы с типизированными файлами приведены в табл. 10.

 

 

Таблица 10

Function Read

Читает данные из типизированного файла

(var F, V1,...,Vn);

F: Vi - переменные такого же типа, что и

 

компоненты файла.

Function Write

Записывает

данные в типизированный

(var F, V1,...,Vn);

файл F: Vi - переменные такого же типа,

 

что и компоненты файла.

Function Seek

Смещает указатель файла F к требуемому

(var F; H: Longint);

компоненту: N - номер компонента файла

 

(первый компонент файла имеет номер0).

Function FileSize

Возвращает

количество компонентов

(var F): Longint;

файла. Чтобы переместить указатель в

 

конец типизированного файла, можно

 

написать:Seek (FileVar, FileSize(FileVar));

Function FilePos

Возвращает текущую позицию в файле,

(var F); Longint;

т.е. номер компонента, который будет

 

обрабатываться следующей операцией

 

ввода-вывода.

8.5Нетипизированные файлы

Вфайлах данного вида тип компонентов не определяется заранее. Работа с ними осуществляется с помощью процедур поблочного считывания и записи. При этом для ЭВМ безразлично содержимое файла и ответственность за корректную работу с информацией полностью лежит на программисте. В рамках данного пособия работа с файлами этого типа не рассматривается. Подробнее с75ними можно ознакомиться в / 1,2 /.

8.6 Средства Delphi для организации работы с файлами

Для организации работы с файлами в Delphi предназначены компоненты TOpenDialog и TSaveDialog. Это стандартные диалоги открытия и сохранения файлов, используемые Windows. Они имеют идентичные свойства, которые рассматриваются ниже.

Свойство FileName: String содержит маршрут поиска и выбранный файл при успешном завершении диалога. Программа может использовать это свойство для доступа к файлу с целью читать из него данные (TOpenDialog) или записывать в него (TSaveDialog). Следует отметить, что пользователь может ввести произвольное имя и, следовательно, указать несуществующий файл. Для записи это не имеет значения, но при чтении отсутствие файла может привести к краху программы. Чтобы избежать этого, можно проверить существование файла глобальной функцией FileExists, или использовать механизм обработки исключительных ситуаций.

Свойство Filter: String используется для фильтрации (отбора) файлов, показываемых в диалоговом окне. Это свойство можно устанавливать с помощью специального редактора или программно. Для доступа к редактору достаточно щелкнуть по кнопке в строке Filter окна Инспектора Объектов. При про-

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

OpenDialog1.Filter:='Текстовые файлы|*.txt|

Файлы Паскаля|*.pas';

задает две маски - для отбора файлов с расширениями PAS и ТХТ.

Установить начальный каталог позволяет свойство

InitialDir: String. Например:

OpenDialog1.InitialDir:='с:\programfiles\borland;

76

С помощью свойства DefaultExt: String[3] формируется полное имя файла, если при ручном вводе пользователь не указал расширение. В этом случае к имени файла прибавляется разделительная точка и содержимое этого свойства.

В диалоговом окне для ручного ввода предусмотрен элемент TEdit, который при желании можно заменить на TComboBox. Для этого необходимо свойству FileEditStyle придать значение fsComboBox вместо умалчиваемого fsEdit. Если выбран комбинированный список, с ним можно связать протокол выбора имен. Для этого используется свойство HistoryList: Tstrings, содержимое которого будет появляться в выпадающем списке. Этот список не пополняется автоматически, поэтому за его содержимым должна следить программа. Например:

if OpenDialogI.Execute then begin

HistoryList.Add(OpenDialog1, FileName);

..................

end;

Настройка диалога может варьироваться с помощью свойства

TOpenOption = (ofReadonly, ofOverwritePrompt, ofHideReadOnly, ofNoChangeDir, ofShowHelp, ofHoValidate,ofAllowMultiSelect, ofExtensionDifferent, ofPathMustExist, ofFileMustExist, ofCreate-

Prompt, ofShareftware,ofNoReadOnlyReturn, ofNoTestFileCreate, ofNoNetworkButton, ofNoLongHames,ofOldStyleDiaiog,

ofNoDereferenceLinks);

Значения этого свойства имеют следующий смысл:

 

ofReadOnly

Устанавливает переключатель ―Только

 

для чтения‖.

 

ofOverwritePrompt

Требует согласия пользователя при

 

записи в существующий файл.

ofHideReadOnly

Прячет переключатель ―Только для

 

77

 

 

 

чтения‖.

 

 

ofNoChangeDir

Запрещает смену каталога.

 

ofShowHelp

Включает в окно кнопку Help.

ofNoValidate

Запрещает

автоматическую

проверку

 

правильности набираемых

в имени

 

файла символов.

 

ofAliowMultiSelect

Разрешает

множественный

выбор

 

файлов.

 

 

ofExtensionDifferent

При завершении диалога наличие это-

 

го значения в свойстве Options говорит

 

о том, что пользователь ввел расшире-

 

ние, отличающееся от умалчиваемого.

ofPathMustExist

Разрешает указывать файлы только из

 

существующих каталогов.

 

ofFileMustExist

Разрешает указывать только сущест-

 

вующие файлы.

 

ofCreatePrompt

Требует подтверждения для создания

 

несуществующего файла.

 

ofShareAware

Разрешает выбирать файлы, исполь-

 

зуемые другими параллельно выпол-

 

няемыми программами.

 

ofNoReadOnlyReturn

Запрещает выбор файлов, имеющих

 

атрибут ―Только для чтения‖.

 

ofNoTestFileCreate

Запрещает проверку доступности се-

 

тевого или локального диска.