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

Программирование. Процедурное программирование. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
Основные возможности процедурного программирования при работе с комбинированными данными…
procedure WriteLn(var F: TextFile; P1; Pn);
Процедура, аналогичная процедуре Write, которая после записи значений допи­сывает в файл спецсимволы перевода строки.
procedure CloseFile(var F: TextFile);
Процедура, завершающая работу с открытым файлом, в результате вызова кото­рой содержимое ассоциированного файла на диске обновляется до последней версии и сохраняется.
function FileExists(FileName: string): Boolean;
Функция, которая проверяет, существует ли файл с именем FileName, и возвра­щает соответствующее значение логического типа.
Замечание. В программе определены специальные текстовые фай­лы – стандартные файлы ввода (Input) и вывода (Output). По умол­чанию они назначены на клавиатуру и монитор. Поэтому, если в процедурах Read/ReadLn и Write/WriteLn файловые переменные не указаны явно, то используются стандартные файлы.
Замечание. В случае если происходит попытка открыть на чте­ние несуществующий файл, либо содержимое файла по формату не соответствует выполняемой операции чтения (например, происхо­дит чтение числа, а следующим символом в файле находится бук­венный символ), либо возникает какая-либо другая ошибочная си­туация при работе с файлом, то в коде программы возникает ис­ключение и программа прекращает работу.
В языке программирования Delphi поддержка типизованных файлов
реализована следующим набором процедур и функций.
procedure AssignFile(var F: file; FileName: string);
Происходит связывание файловой переменной F с именем файла FileName на диске.
Примеры применения процедуры AssignFile
AssignFile(F, 'numbers.dat'); AssignFile(Catalog,'C:\MyFiles\catalog.dat');
Замечание. Если файл хранится в одной директории с проектом, то достаточно указать его короткое имя (при стандартных на-
61
Глава 2
стройках сборщика проекта Delphi). Если файл хранится вне про­екта, то необходимо указывать его полное имя, начиная с диска размещения. Для учебных задач рекомендуется все файлы хранить вместе с проектом. Так будет проще переносить проект с одного компьютера на другой, при этом не будет необходимости исправ­лять имя файла в программе.
Для начала работы с файлом он должен быть открыт. Для этого при-
меняются операции Reset или Rewrite.
procedure Reset(var F: file);
Оператором Reset открывается существующий файл, связанный с файловой пе­ременной F.
procedure Rewrite(var F: file);
Оператор Rewrite создает и открывает новые файлы. При открытии существую­щего файла при помощи оператора Rewrite его содержимое будет стерто.
В отличие от текстовых типизированные файлы допускают чередо-
вание операций записи и чтения независимо от того, каким оператором (Reset или Rewrite) он был открыт.
Далее перечислены основные процедуры и функции для работы
с типизированными файлами.
function FileExists(FileName: string): Boolean;
Функция возвращает True, если файл с указанным именем существует на диске.
procedure CloseFile(var F: file);
Производится закрытие файла, связанного с файловой переменной F.
procedure Read(var F: file; V1, V2,...,Vn);
Осуществляется чтение из файла, связанного с файловой переменной F, указан- ного списка переменных V1, V2,..., Vn. Все перечисленные переменные должны иметь тип компонент файла.
procedure Write(var F: file; V1, V2,...,Vn);
Осуществляется запись в файл, связанного с файловой переменной F, указанного списка переменных V1, V2, ..., Vn. Все перечисленные переменные должны иметь тип компонент файла.
procedure FileSize(var F: file):Integer;
Функция возвращает общее количество записей в файле.
62
Основные возможности процедурного программирования при работе с комбинированными данными…
Все элементы типизированного файла одного типа, а значит, и одно-
го размера. Благодаря этому возможен произвольный доступ к элементам типизированного файла.
Произвольный доступ к элементам файла осуществляется операто-
ром Seek. Текущее положение указателя файла возвращается функцией FilePos.
procedure Seek(var F: file; k: Integer);
Процедура устанавливает указатель файла на элемент с указанным номером k, нумерация начинается с 0.
procedure FilePos(var F: file):Integer;
Функция возвращает текущее положение указателя.
Примеры применения процедуры Seek
Seek(F, 0); // Перемещение указателя на начало файла Seek(F, FileSize(F)); // Перемещение указателя в конец файла
Как и для текстовых файлов, ситуация «конец файла» диагностиру-
ется функцией EoF (файловая переменная).
Пример программы № 9
В текстовом файле «book.txt» записан некоторый текст. Подсчи-
тать число слов в нем.
Разработка программы Воспользуемся кодом подсчета количества слов в строке, разрабо-
танным в примере программы № 8, и оформим его в виде функции CountWords, получающей на вход строку и возвращающей число слов в ней в качестве результата.
По заданию требуется открыть файл на чтение, построчно его считать
и просуммировать количество слов по всем строкам. Оформим этот алго­ритм в виде функции CountWordsInFile, принимающей в параметре имя входного текстового файла и возвращающей общее число слов в нем в каче­стве результата. Перед началом чтения данных из файла, как и в предыду­щем примере, потребуется вызвать процедуры AssignFile и Reset. Чтение строк из файла организуем в виде цикла с условием проверки достижения конца файла not EoF(F). На каждой итерации цикла будем читать строку из файла и помещать ее в переменную S, вычислять при помощи функции CountWords количество слов в ней и накапливать результат в переменной Result.
63
Глава 2
Текст программы полностью приведен в листинге 9.
Листинг 9. Пример программы № 9
program Example9;
{$APPTYPE CONSOLE}
uses SysUtils, Windows; const Separators = [',', '.', '!', '?', '-', ' '];
function CountWords(S: string): Integer; var CharType: Boolean; I: Integer; begin
S := ' ' + S + ' '; Result := 0; CharType := true; for I := 1 to Length(S) do if (S[I] in Separators) <> CharType then begin if CharType then Result := Result + 1; CharType := not CharType; end;
end;
function CountWordsInFile(FileName: string): Integer; var F: TextFile; S: string; begin
Result := 0; AssignFile(F, FileName); Reset(F); while not Eof(F) do begin ReadLn(F,S); Result := Result + CountWords(S); end; CloseFile(F);
end; begin
SetConsoleOutputCP(1251); WriteLn('Количество слов = ', CountWordsInFile('book.txt')); ReadLn; end.
64
Основные возможности процедурного программирования при работе с комбинированными данными…
Результат работы программы для текстового файла
Привет! Как дела?
будет следующий:
Количество слов = 3
Создание типизированного файла
Одной из областей применения типизированных файлов является
хранение данных о наборе объектов, характеризующихся набором значе­ний. Для этой цели используются типизированные файлы записей. Приве­дем пример процедуры CreateFile создания файла записей о мебели, харак­теризующейся полями: наименование предмета мебели, материал, цена.
Пример процедуры создания типизированного файла
type
// Запись - предмет мебели: TFurniture = record Name: string[20]; // Наименование Material: string[50]; // Материал Price: Real; // Цена end; TFurnitureFile = File of TFurniture; // Файл записей // Процедура создания типизированного файла
procedure CreateFile(FileName: string); var
F: TFurnitureFile; Count, I: integer; Item: TFurniture; begin AssignFile(F, FileName); Rewrite(F); // Создание нового файла Write(' Введите количество записей: '); ReadLn(Count); for I := 1 to Count do begin WriteLn(' Запись №', I); Write(' Введите наименование: '); ReadLn(Item.Name); Write(' Введите материал: '); ReadLn(Item.Material); Write(' Введите цену: '); ReadLn(Item.Price);
65
Глава 2
Write(F, Item); end; CloseFile(F); end;
Чтение данных из типизированного файла
После того как файл создан, он пригоден для обработки (например,
для просмотра). Обработка (просмотр) осуществляется строго последова­тельно, начиная с первой компоненты файла. При этом на каждом шаге доступна лишь одна компонента файла.
Следующий пример демонстрирует просмотр ранее созданного файла.
Процедура вывода содержимого типизированного файла
// Процедура печати содержимого типизированного файла на экран
procedure ReadData(FileName: string); var
FileData: TFurnitureFile; Item: TFurniture; begin AssignFile(FileData, FileName); Reset(FileData); while not EoF(FileData) do begin Read(FileData,Item); with Item do begin WriteLn(Name:20, Material:20, Price:10:2); end; end; CloseFile(FileData); end;
Контрольные вопросы и задания
1. Какие операции разрешены для записи в целом?
Как описывается файловая переменная для текстового файла, ти-
2.
пизированного файла?
Какие существуют способы открыть файл? В чем их отличие (для
3.
текстового файла, для типизированного файла)?
Чем отличаются текстовые файлы от файлов file of string?
4.
Перечислите действия, которые выполняет процедура Seek? Что
5.
возвращают функции FileSize и FilePos?
66
Основные возможности процедурного программирования при работе с комбинированными данными…
2.3. Расширенная работа с файлами. Типизированные константы. Преобразование типов
Проверка существования файла
При работе с файлами в программе часто приходится открывать
файлы, существующие на диске. Предполагается, что эти файлы сущест­вуют и могут быть открыты. Однако бывают случаи, когда файл не суще­ствует или поврежден. Открыть такой файл не представляется возможным.
Далее приведен текст функции TestFile, проверяющей корректность
имени файла. Параметром функции является строка FileName (имя файла). Функция возвращает логическое значение True, если нет ошибок при от­крытии файла; False, если имеется ошибка, например, файла с таким име­нем не существует на диске.
Проверка корректности имени файла
// Функция тестового открытия файла
function TestFile(FileName: string):boolean; var FileIn: TextFile; begin
AssignFile(FileIn, FileName); {$I-} Reset(FileIn); {$I+} Result := IOResult <> 0; if not Result then CloseFile(FileIn); end;
В функции производится пробное открытие файла для чтения при
помощи функции Reset. Однако если файл не существуют на диске либо его невозможно открыть, произойдет ошибка ввода/вывода, программа за­вершится и выведется сообщение об ошибке. Для возможности отслежи­вать ошибки ввода/вывода оператор Reset помещен в блок с выключенной опцией проверки ввода/вывода {$I-}. Если происходит ошибка вво­да/вывода и проверка ввода/вывода выключена, то все последующие опе­рации ввода/вывода игнорируются, пока не будет сделано обращение к функции IOResult, при котором очищается внутренний флаг ошибки.
Добавление записей в конец типизированного файла
Для добавления записей в файл используются следующие стандарт-
ные процедуры и функции:
67
Глава 2
procedure Seek(var F: file; k: Integer);
Эта процедура устанавливает указатель (курсор) файла на элемент с указанным номером k.
procedure FilePos(var F: file):Integer;
Функция возвращает текущее положение файлового курсора.
В следующем примере представлена процедура добавления записи
в конец файла.
Процедура добавления записи в конец файла
procedure AddData(FileName: string); var
Item: TFurniture; F: TFurnitureFile begin Seek(F, FileSize(F)); {Установить указатель на последнюю компоненту файла} Write(' Введите наименование: '); ReadLn(Item.Name); Write(' Введите материал: '); ReadLn(Item.Material); Write(' Введите цену: '); ReadLn(Item.Price); Write(F, Item); end;
Замена записи в файле
Если известен номер заменяемой записи, то можно ее заменить, ис-
пользуя оператор Seek. В случае когда известно содержимое записи, ис­пользуется последовательный поиск записи в файле. Ниже представлена процедура Swap перестановки двух записей в типизированном файле.
Процедура обмена местами двух записей в файле
procedure SwapData(var F: TFurnitureFile; Index1, Index2: Integer); var
Item1, Item2: TFurniture; begin // Считывается запись на позиции Index1 Seek(F, Index1); Read(F, Item1); // Считывается запись на позиции Index2 Seek(F, Index2); Read(F, Item2); // На позиции Index2 записывается первая запись Seek(F, Index2); Write(F, Item1); // На позиции Index1 записывается вторая запись Seek(F, Index1); Write(F, Item2); end;
68
Основные возможности процедурного программирования при работе с комбинированными данными…
Сортировка записей в файле
Далее приведена рекурсивная процедура Sort сортировки записей
в типизированном файле, основанная на сортировке выбором. В этом слу­чае в файле последовательным просмотром ищется запись с наименьшим значением поля Price и переставляется в начало неотсортированной части файла (первая запись и минимальная меняются местами). После этого про­цесс сортировки повторяется в неотсортированной части файла.
Процедура сортировки записей в типизированном файле
procedure Sort(var F: TFurnitureFile; I: Integer = 0); var
Item, Item_1, Item_min: TFurniture; Index, Index_min: Integer; begin // Устанавливаем указатель файла на запись с номером I Seek(F, I); Read(F, Item_1); {Далее в файле осуществляется поиск записи с наименьшим значением поля Price} Item_min:=Item_1; Index_min:= I; Index := I+1; while not EoF(F) do begin Read(F,Item); // Считываем очередную запись {Если поле Price текущей записи меньше поля Price минимальной записи} if Item.Price < Item_min.Price then begin // Переписываем минимальную запись и ее номер Item_min:=Item; Index_min:=index; end; Index := Index+1; end; {Если минимальная запись не совпадает с первоначальной, то меняем записи местами} if Index_min <> I then SwapData(F, Index_min, I); {Если в файле остались неотсортированные записи, то продолжаем рекурсивно сортировку} if I < FileSize(F)-1 then Sort(F,I+1); end;
Существуют и другие дополнительные возможности работы с фай-
лами. Например, определение эффективного буфера обмена данными между оперативной и внешней памятью, введение дополнительных раз-
69
Глава 2
делителей между элементами текстовых файлов для обмена файловыми данными и т. п.
Типизированные константы
В Delphi допускается использование типизированных констант.
В этом случае после имени константы через двоеточие указывается ее тип, а затем через знак равенства – ее значение. Они описываются в разделе объявления констант следующим образом:
<идентификатор> : <тип> = <значение>;
где <идентификатор> – идентификатор константы, <тип> – тип константы, <значение> – значение константы.
Типизированные константы могут быть любых типов, кроме файлов.
В отличие от нетипизированных констант типизированные константы не могут быть использованы при объявлениях границ типа-дипазона.
Обычно типизированные константы используются при работе со
сложноструктурированными данными (массивы, множества, записи).
При объявлении типизированной константы-массива ее начальные
значения перечисляются через запятую в круглых скобках. В случае объ­явления многомерной константы-массива множество констант, соответст­вующих каждому измерению, заключается в дополнительные круглые скобки. При объявлении массива символов допускается задание символь­ной строки соответствующей длины.
Константы-массивы
type TVector = array[1..5] of integer; {Одномерный массив} TMatrix = array[1..5] of TVector; {Двумерный массив} const // Константа типа TVector V: TVector = (1, 1, 1, 1, 1); // Константа типа TMatrix: U: TMatrix = ((1, 0, 0, 0, 0), (0, 1, 0, 0, 0), (0, 0, 1, 0, 0), (0, 0, 0, 1, 0), (0, 0, 0, 0, 1)); // Константа символьного массива Letters: array[0..9] of Char = 'АЕЁИОУЫЭЮЯ'; end;
При объявлении константы записи ее значение представляет собой
список полей в виде последовательности вида: имя поля, двоеточие и кон-
70
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]