Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Praktikum_po_informatike_2003_c_uvelichennym_og....doc
Скачиваний:
31
Добавлен:
12.11.2018
Размер:
5.3 Mб
Скачать

§ 14 Обращение к внешним устройствам

В процессе работы программиста часто возникают задачи, связанные с записью информации на внешний магнитный диск и считывания с него информации, сохранённой ранее. Поэтому язык программирования должен содержать средства для организации хранения информации на внешних ЗУ и доступа к этой информации, оформленной в виде файлов. Под файлом в данном случае подразумевается область памяти на внешнем ЗУ, способная хранить некоторую совокупность информации. В эту область можно поместить, а можно извлечь из неё некоторые данные. Эти действия имеют общее название ввод-вывод. Для организации работ по вводу-выводу в программе могут быть использованы специальные переменные, которые являются представителями файлов в программе. Для работы с такими представителями файлов в языке Паскаль имеется специальная группа типов, называемая файловыми типами. Использование переменных файловых типов предполагает интерпретацию файла как потенциально бесконечного списка значений одного и того же базового типа. Например,

Var

F: file of integer;

понимается как определение в программе под именем F списка неопределённого количества целых чисел, расположенного на некотором внешнем ЗУ. С каждой переменной файлового типа связано также понятие текущего указателя файла. Текущий указатель можно понимать как некоторую скрытую переменную, которая обозначает (указывает на) некоторый конкретный элемент файла. Графически интерпретацию файла, связанного с переменной F, можно представить в виде:

Целое

Целое

Целое

Целое

Текущий указатель

Как правило, все действия с файлом (чтения из файла, запись в файл) проводятся поэлементно, а текущий указатель перемещается от одного элемента к другому. Все элементы файла считаются пронумерованными. Начальный элемент имеет нулевой номер. Один и тот же внешний файл в разных программах может интерпретироваться по-разному, например, как последовательность целых чисел или как последовательность символов.

Файловый тип задаётся в программе с помощью служебных слов file of, за которыми следует тип элементов файла (базовый тип). Базовый тип может быть любым, кроме файлового. Синтаксическая диаграмма для файловых типов имеет вид

Object Pascal имеет также средства взаимодействия с файлами несколько иной структуры, т.н. текстовыми файлами. Содержимое текстовых файлов рассматривается как последовательность строк переменной длины, разделённых специальной комбинацией символов, называемой «конец строки». Как правило, эта информация строится из управляющего кода #13 «перевод каретки» и управляющего кода #10 «перевод строки». Текстовый файл завершается специальным кодом #26 «конец файла». В большинстве случаев используются операции, включающие соответствующие действия. Поэтому нет необходимости непосредственно указывать коды в программе. Описание файловых переменных перечисленных типов производится следующим образом:

Var f1 : file of char; {файл содержит только символы}

f2 : file of real; {файл содержит только действительные числа}

f3 : textfile; {текстовый файл. Слово «textfile» считается идентификатором стандартного типа}. Текстовые файлы для хранения информации требуют больше места на винчестере, чем файлы других типов, однако, упрощают решение целого ряда задач, стоящих перед пользователем.

Операции над файловыми переменными можно разбить на 4 основные группы:

  1. Установочные и завершающие операции;

  2. Собственно ввод-вывод;

  3. Перемещение по файлу;

  4. Специальные операции.

 Установочные и завершающие операции с файлами включают 4 операции, реализованные в виде стандартных процедур со следующими именами:

AssignFile(<имя файловой переменной>, <имя файла>)

Reset(<имя файловой переменной>)

Rewrite (<имя файловой переменной>)

Flush(<имя файловой переменной>)

CloseFile(<имя файловой переменной>)

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

Примеры:

AssignFile (F,'a:\mydir\myfile.dat');

После выполнения данного вызова файловая переменная F будет связана с дисковым файлом myfile.dat, расположенным в каталоге mydir из корневого каталога диска a.

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

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

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

Операции ввода-вывода – чтение и запись информации. Чтение информации из файла осуществляется процедурами :

Read или Readln (для текстовых файлов).

Запись информации в файл :

Write или Writeln (для текстовых файлов) .

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

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

Функция  EoF вызывается с одним параметром- файловой переменной и

возвращает логическое значение true или false в зависимости от того, достигнут ли конец файла. Если файл использовался для чтения, то возникает ситуация "конец файла" (и, соответственно, значение true, возвращаемое функцией EoF) означает, что все элементы файла прочитаны. Поэтому возможны конструкции типа if EoF(f) then… или repeat … until EoF(f)

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

информацию из программы. Первым параметром этой процедуры должна быть

файловая переменная, открытая процедурой Rewrite. Далее должен следовать список выражений, тип которых совпадает с базовым типом файла из первого параметра. Значение очередного выражения будет помещено в файл в место, отмеченное текущим указателем. После этого текущий указатель передвинется на одну позицию, и действия повторятся для следующего выражения из списка параметров вызова процедуры Write. Помимо процедур Read и Write, для текстовых файлов имеются две их модификации- процедуры Readln и Writeln. Эти процедуры осуществляют те же действия, что и соответствующие процедуры Read и Write, но после операций чтения и записи производят переход к следующей строке текстового файла. Заметим ,что операция Read автоматически переходит к следующей строке только в случае исчерпания текущей строки; процедура Readln позволяет совершить этот переход ,не дожидаясь исчерпания строки.

Для того, чтобы проверить, достигнут ли конец текущей строки, используется функция  EoLn. Эта функция вызывается с одним параметром (файловой переменной ) и возвращает логическое значение: true, если текущая строка исчерпана, и false в противном случае.

В качестве примера рассмотрим программу расчёта площади многоугольника при условии, что исходные данные (координаты его вершин) находятся в файле на жёстком диске. Фрагмент программы считывания данных из текстового файла при условии, что каждое число расположено на отдельной строке и общее количество чисел известно, имеет вид:

AssignFile(f,'C:\treug.dat');

Reset(f);

for i:=1 to n do

for j:=1 to 2 do

begin

Readln(f,x[i,j])

end;

CloseFile(f);

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

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

AssignFile(f,'C:\treug.dat');

Reset(f);

i:=0;

repeat

i:=i+1;

for j:=1 to 2 do

begin

Readln(f,x[i,j]);

n:=i

end;

until EoF(f);

CloseFile(f);

Здесь использован оператор цикла с постпроверкой условия, но мог быть использован и оператор с предпроверкой условия. Завершение процесса считывания определяется значением, возвращаемым функцией EoF(f). Во всех приведенных выше примерах при описании массива необходимо резервировать память, исходя из максимального возможного количества его элементов

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

Array of <тип элементов>

Задание размера динамического массива производится с использованием процедуры SetLength(var S; N: integer). Здесь S – идентификатор динамического массива, N – количество элементов в массиве. Таким образом, в результате выполнения процедуры SetLength количество элементов динамического массива S устанавливается равным N. Выполнять какие-либо операции с динамическим массивом и его элементами можно только после установления его длины. Первый элемент динамического массива всегда имеет номер 0, а последний – номер N-1. В качестве элементов могут быть использованы данные любых типов, в том числе и массивы. Следовательно, пользователь имеет возможность создавать многомерные динамические массивы. Формат описания многомерного динамического массива следующий: S: array of arrayof array of <тип данных>. Например, описание двумерного динамического массива действительных чисел имеет вид S: array of array of real. Установка размеров производится отдельно для каждого индекса SetLength(var S; N1, N2: integer). Возможна и другая процедура задания размеров многомерного динамического массива:

SetLength(var S; N: integer) //Массив включает N строк

SetLength(var S[0];M0: integer);// M0, Mi, M N-1, числа, но не элементы массива.

…………………………………..

SetLength(var S[I];Mi: integer);

…………………………………..

SetLength(var S[N-1];M N-1: integer);

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

Для освобождения памяти после завершения обработки данных динамического массива используется процедура Finalize(S). Эту процедуру можно применять либо ко всей матрице, либо к одной её строке. Ниже в качестве примера приведена процедура считывания элементов двумерного динамического массива с жёсткого диска и записи их в таблицу.

var

s:array of array of integer;

m,n,i,j: integer;

f: TextFile;

begin

AssignFile(f,'mas.txt');

Reset(f);

Readln(f,m,n);

SetLength(S,m,n);

StringGrid1.ColCount := m+1;

StringGrid1.RowCount := n+1;

for j:=0 to n-1 do

begin

for i:=0 to m-1 do

begin

Read(f,s[i,j]);

StringGrid1.Cells[i+1,j+1]:=IntToStr(S[i,j])

end;

Readln(f)

end;

CloseFile(f);

Finalize(s);

end;

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

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