4609

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

Реферат

Информатика, кибернетика и программирование

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

Русский

2012-11-23

231.5 KB

3 чел.

Введение

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


1. ОСНОВЫ РАБОТЫ С ФАЙЛАМИ

1.1. Физические файлы и файловые переменные

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

С другой стороны, файл — это одна из многих структур данных, используемых в программировании. Файл в таком понимании называют логическим файлом.

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

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

0

1

2

N

байт

байт

байт

...

байт

Структура логического файла — это способ восприятия файла в программе. Образно говоря, это «шаблон», через который рассматривается физическая структура файла. Таким «шаблонам» соответствуют типы данных, допустимые в качестве компонент файлов, например:

file of Byte (файл байтов)

байт

байт

байт

...

байт

байт

EOF

file of Char (файл символов)

код символа

код символа

код символа

...

код символа

код символа

EOF

file of Integer (файл целых чисел)

целое со знаком

целое со знаком

целое со знаком

...

целое со знаком

EOF

file of T (файл записей)

где

T = record

    a: Byte;

    b: Char;

    c: Integer

end;

байт

код символа

целое со знаком

...

байт

код символа

целое со знаком

EOF

Нумерация элементов файла выполняется слева направо, начиная от 0 (кроме текстовых файлов). Количество элементов файла в каждый момент времени неизвестно, но известно, что в конце файла располагается специальный символ конца файла EOF (End-of-File), в качестве которого используется управляющий символ ASCII с кодом 26 (Ctrl+Z).

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

  1.  по типу (логической структуре):
    •  типизированные файлы (все элементы файла одного типа, например, real или integer);
    •  текстовые файлы (состоят из различных символов и являются разновидностью файлов типа file of char);
    •  нетипизированные файлы (бестиповые – не имеют жестко установленных единиц чтения/записи);
  2.  по методу доступа к элементам файла:
    •  файлы последовательного доступа – для доступа к конкретному элементу файла необходимо предварительно просмотреть все предшествующие элементы;
    •  файлы прямого доступа – обеспечивают непосредственный доступ к нужному элементу файла без учета того, что было просмотрено ранее.

В программах файлы представляются файловыми переменными определенного типа. Они являются представителями физических файлов в программе.

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

Type

 Имя_типа_файла = file of Тип_элементов;

Var

 Имя: Имя_типа_файла;

либо

Var

 Имя: file of Тип_элементов;

где Имя – имя файловой переменной;

Имя_типа_файла – идентификатор, используемый для обозначения типа файловых переменных.

Объявленные переменные файлового типа запрещено использовать в выражениях!!!

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

Type

 TPhone = record          // Объявление записи

   FN,LN: string[20];

      PN: string[15];

  Listed: Boolean

 end;

 TPhoneList = file of TPhone;  // Тип файл записей

Var

 FV: TPhoneList;   // Файловая переменная файла записей

 RV: TPhone;       // Переменная для доступа к записи

 rs: file of char; // Файловая переменная файла символов 

 kf: file of real; // Файловая переменная файла вещественных чисел 

 f: file of integer; // Файловая переменная файла целых чисел 

А вот следующие определения типов недопустимы:

Type

 F1 = file of file of char;

 F2 = file of TextFile;

 F3 = file of array[0..M] of file of real;

Допустимо и такое объявление типизированного файла записей:

Type

 Karta = file of record

           Dlina: byte;

             Ves: real

                 end;

Var

 KartFile: Karta;

Var

 KartFile: file of record;

              Dlina: byte;

                Ves: real

                   end;

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

Файл, компонентами которого являются данные символьного типа, называется символьным (или текстовым).

Описание текстового файла в общем виде выглядит так:

Имя: TextFile;

Например:

Type

 TText = TextFile;

var

  Doc1, Doc2, Kniga: TText;

либо

Var

  Doc1, Doc2, Kniga: TextFile;

В текстовых файлах помимо признака конца файла EOF используется дополнительный признак конца строки – EOL (End-of-Line), который представляет собой последовательность из двух символов кода ASCII — символа с кодом #13возврат каретки») и символа с кодом #10перевод строки»).

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

код символа

код символа

...

код символа

код символа

EOL

код символа

код символа

...

код символа

EOL

код символа

код символа

...

EOL

код символа

код символа

...

код символа

код символа

EOF

Нетипизированные файлы рассматриваются как последовательности байтой. При их объявлении указывается только ключевое слово file, например,

var Fi,Fo: file;

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

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

Элементы массивов и записей могут иметь файловые типы. Например, допустимы следующие определения типов:

Type

 Arrfile = array[1..N] of file of Student;

 Rcrfile = record

             Data: TextFile;

             Temp: char

           end;

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

Con

- консоль (пульт управления): для ввода – это клавиатура, для вывода – экран монитора;

Trm

- терминал: для ввода – это клавиатура, для вывода – экран. При вводе информация не отображается на экране и не может редактироваться;

Kbd

- клавиатура – вводимая информация на экране не отображается;

Lst

- построчное печатающее устройство(принтер);

Aux

- вспомогательное устройство;

Usr

- устройство пользователя. Применяется при написании собственных драйверов пользователя для организации нестандартного ввода-вывода с внешними устройствами;

Input

- основной файл для ввода (назначается устройствам Con или Trm);

Output

- основной файл для вывода (назначается устройствам Con или Trm).

Система сама открывает и закрывает эти файлы, поэтому к ним не применяются процедуры Assign, Flush, Reset, Rewrite.

1.2. Общие принципы работы с файлами

Последовательность работы со всеми типами файлов следующая:

  •  размещение в памяти (объявление) файловой переменной соответствующего типа;
  •  связывание файловой переменной с именем дискового файла (как правило, указывается полное имя – путь к файлу и его имя);
  •  открытие/создание файла – выделение ресурса ОС для обмена информацией между дисковым файлом и программой. Файл может быть открыт как для чтения, так и для записи; для некоторых типов файлов возможно открытие одновременно для чтения и записи;
  •  непосредственно обмен информацией – чтение/запись данных из/в файл. При этом возможны перемещения по файлу – изменение позиции чтения/записи;
  •  закрытие файла – освобождение ресурса ОС.

Работа с файловой переменной начинается со связывания ее с конкретным физическим файлом. Для всех типов файлов операция сопоставления файловой переменной с именем файла на диске однотипна и выполняется с помощью процедуры:

AssignFile(f,S);

где f – имя объявленной файловой переменной;

     S – выражение строкового типа, определяющее полное имя файла.

Например:

AssignFile(f,'d:\result.txt');

{Файловая переменная f связывается с физическим файлом result.txt, находящимся в корневом каталоге диска d:}

AssignFile(fk,'c:\Date\PZ_06\students.dat');

{Файловая переменная fk связывается с физическим файлом students.dat, находящимся на диске с: в подкаталоге PZ_06 каталога Date}

fname:='otchet.doc'; //Строковой переменной fname присваивается

                      //имя файла otchet.doc

AssignFile(m5, fname);

{Файловая переменная m5 связывается с физическим файлом otchet.doc, имя которого передается через строковую переменную fname}

sl:='c:\mydir\book'; s2:='txt'; 

AssignFile(f,sl+'.'+s2);

{Связывает файловую переменную f с файлом c:\mydir\book.txt}

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

...

var f: textfile; //Вводится файловая переменная текстового файла

   fn, st: string;

begin

 ...

 fn:='default.dat';

 write('Если Вы нажмете <ENTER>, f будет ');

 writeln('связан с файлом default.dat');

 write('Для изменения связывания f введите имя файла:');

 readln(st);

 if st<>'' then fn:=st;

 assignfile(f,fn); 

Если нужно связать f с файлом, внешнее имя которого default.dat, достаточно нажать на клавишу <ENTER>. Для другого связывания нужно набрать на клавиатуре внешнее имя, например, newname.dat, и нажать <ENTER>.

Работать с элементами связанного файла можно только после его открытия. Оно задается процедурами, которые рассматриваются ниже. Однако сейчас опишем закрытие файла с помощью процедуры close. Ee вызов имеет такой вид.

Close(f);

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

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

  •  Попытка закрыть уже закрытую или еще не открытую файловую переменную приводит к аварийному завершению программы.

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

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

Номер доступного элемента в последовательности элементов файла является значением специальной неявной переменной — файлового указателя (рис. 1). Номер доступного элемента (значение указателя) изменяется при выполнении подпрограмм обработки файлов.

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

Итак, в состав файловой переменной входят последовательность элементов физического файла, номер доступного элемента и состояние. Обозначим это в виде (F, i, s), где Fпоследовательность значений <f0, f1, ... , fn>, i - номер доступного элемента, s — состояние. Нумерация элементов начинается с 0. Состояния чтения и записи обозначаются буквами R и W соответственно.

Рис. 1. Физический файл и файловый указатель

Например, выражение (<11, 12, 13, l4>, 1, R) обозначает состояние файла, в котором второе из последовательности чисел 11, 12, 13, 14 (с номером 1) доступно для чтения. Выражение (<>, 0, W) обозначает пустой файл, к которому можно добавить новый элемент (с номером 0) и записать в него какое-нибудь значение. Описанные состояния представлены на рис. 2; стрелки обозначают файловые указатели и указывают на доступные элементы.

Рис. 2. Состояния файла

1.3. Последовательная запись в типизированные файлы

Файл, предназначенный для записи, следует открыть с помощью процедуры rewrite:

ReWrite(f);

которая создает и открывает для чтения/записи новый (пустой) внешний файл, с именем, которое указывалось при связывании файловой переменной f.

После вызова ReWrite(f); значение f можно представить как (<>, 0, W), т.е. независимо от предыдущего состояния f последовательность в файле становится пустой – указатель чтения/записи устанавливается на начало файла. Эта процедура вызывается для создания нового физического файла или обновления старого с уничтожением предыдущих данных. После ее выполнения файл называется установленным в начальное состояние для записи.

Запись в файл задается процедурой write. При выполнении ее вызова

Write(f, выражение_типа_компонентов_файла);

значение выражения вычисляется и присваивается доступному элементу файла, после чего указатель доступного элемента сдвигается на 1 элемент.

Например, рассмотрим следующую программу.

program ...

var f: file of integer;

   x: integer;

begin

...

..assignfile(f,'d:\chisla.dat'); //связывание f с файлом

...

 rewrite(f);     //открытие файла для записи

 x:=2;

 write(f, 1);    //запись в 0-й элемент 1 

 write(f, x);    //запись в 1-й элемент 2

 write(f, x*x);  //запись во 2-й элемент 4

end.

После третьего вызова write значением f будет (<1, 2, 4>, 3, W).

Вообще, значение (<f0, f1, ... , fn-1>, n, W) файловой переменной f после выполнения write(f, выражение) изменяется на (<f0, f1, ... , fn-1, V>, n+1, W), где Vзначение выражения.

В вызове write допустимо произвольное число аргументов соответствующего типа:

Write(f, выражение1, ... , выражениеn);

Такой вызов выполняется на самом деле как последовательность

Write(f, выражение1); ... ; Write(f, выражениеn);

Например, вместо 

write(f, 1); write(f, x); write(f, x*x);

можно записать

write(f, 1, x, x*x);

  •  К типизированным файлам неприменима процедура writeln. Она определена только для текстов.

1.4. Последовательное чтение типизированных файлов

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

Reset(f);

После вызова reset файл устанавливается в начальное состояние для чтения, а номером доступного элемента становится 0 независимо от того, есть ли элементы в файле. Значение f можно представить как (f, 0, R).

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

Доступный элемент файла читается с помощью процедуры read. Ee вызов имеет вид:

Read(f, v);

где v — имя переменной типа, совместимого по присваиванию с типом элементов файла.

Значение доступного элемента присваивается переменной v, а доступным становится следующий элемент.

Например, при чтении read(f, x) файла f со значением (<11, 12, 13>, 0, R) переменная x получает значение 11, а значение f можно представить как (<11, 12, 13>, 1, R), т.е. доступным становится элемент со значением 12.

Вообще, если файл содержит n элементов с номерами от 0 до n – 1, и номер доступного компонента i меньше n, то вызов read(f, x) задает присвоение переменной x значение i-го элемента и переход от значения файла (F, i, R) к (F, i+1, R). Если же i = n, то говорят, что файл f прочитан, или исчерпан (в частности, если он пустой, т.е. F = <>), и вызов read приводит к аварийному завершению программы.

В вызовах процедуры read можно указывать произвольное количество аргументов. Вызов

Read(f, выражение1, ... , выражениеn);

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

Read(f, выражение1); ... ; Read(f, выражениеn);

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

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

Определение, прочитан ли файл, выполняется с помощью функции eof. Из вызова eof(f) возвращается булево значение false, если есть доступный элемент файла, т.е. i < n в значении файловой переменной (<f0, f1, ... , fn-1>, i, R). Значение true возвращается, если i = n, т.е. файл прочитан.

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

2. РАБОТА С ТЕКСТАМИ

2.1. Особенности организации текстов

Для представления текстов на внешних носителях определен специальный тип с именем textfile. Файлы этого типа называются файлами-текстами или просто текстами. Для текстов определены специфические подпрограммы, часть которых связана с разбиением текстов на строки.

Способ, по которому задается конец строки физического файла, зависит от файловой системы, и его можно даже не знать. Достаточно рассматривать строку файловой переменной как последовательность, которая заканчивается специальным символом <eol>. Строка, состоящая лишь из этого символа, называется пустой.

Определить, доступен ли <eol> в файле в данный момент, можно с помощью функции eoln:

eoln(f).

Из вызова eoln(f) возвращается true, если доступен <eol>, и false в противном случае. Вот пример текста, который говорит сам за себя:

TEKCT<eol>CОCTОИT<eol><eol>И3 ПЯТИ СТРОК;<еоl>ТРЕТЬЯ ПУСТАЯ<еоl>

Конечно, приятнее читать эту последовательность в виде:

TEKCT<eol>

COCTOИT<eol>

<eol>

ИЗ ПЯТИ CTPOK;<eol>

ТРЕТЬЯ ПУСТАЯ<еоl>

Чтобы определить, прочитан ли текст полностью, вызывается функция eof. В текстах признак конца может задаваться не только средствами операционной системы, но и специальными символами в самом физическом файле. Для программ, написанных на Delphi, таким символом является chr(26). Например, приведенный текст в физическом файле на самом деле заканчивался бы не <eol>, a <eol><chr(26)>. Если в тексте f доступен <chr(26)>, то из вызова eof(f) возвращается true, a при доступности другого символа — false.

Имя input можно не указывать в вызовах и вместо eof(input) или eoln(input) писать eof или eoln.

2.2. Запись в текст

Пусть f — имя файловой переменной типа textfile.

Текст устанавливается в начальное состояние для записи (опустошается) при вызове процедуры

rewrite(f);

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

append(f);

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

Символы записываются в текст при вызовах процедур write и writeln. Их первый аргумент — имя файловой переменной. При выполнении вызова

write(f, выражение_базового_типа_или_строка);

вычисляется значение выражения, затем по значению создается константа, т.е. последовательность символов, изображающих значение, и копируется в текст f. Например, при выполнении вызова

write(f, trunc(sqrt(9999)));

в файл дописываются два символа '9' и '9', изображающие число 99.

В вызове можно записать несколько выражений через запятую.

write(f, выражение1, выражение2, ...)

Например, при x = 2 и вызове

write(f, 'x=', x, '; x**2=', sqr(x));

в файл выводится последовательность символов x=2; x**2=4. Такой вызов в действительности выполняется как последовательность вызовов

write(f, выражение1); write(f, выражение2); ...

Процедура writeln отличается лишь тем, что при вызове

writeln(f, список_выражений_базовых_типов_или_строк);

за последней константой в текст добавляется признак конца строки <eol>. Список выражений здесь может быть пустым — тогда только добавляется <eol>.

В вызовах процедур write и writeln после выражения через двоеточие можно указать ширину поля W для записи значения выражения, например write(f, sqr(x):2);. Здесь W=2. Предположим, что для записи значения выражения в действительности нужно L символов. В последнем вызове L=1 при x<4, L=2 при 3<x<10, L=3 при 9<x<34 и т.д. Если L<W, то перед символами значения добавляются W-L пробелов; а если L>W, то выводятся все символы. Таким образом, при x=3 печатаются пробел и 9, а при x=100 — все пять символов 10000.

После выражения действительного типа можно также указать количество N цифр дробной части, которые выводятся после десятичной точки, например, write(f, sqrt(x):7:3);. Если N указано, то выводится константа с фиксированной точкой и N цифрами после точки, иначе — нормализованная с порядком. В данном случае при x=2 выводятся два пробела и 1.414. Последняя цифра является результатом округления. Некоторые другие детали могут определяться системой программирования.

2.3. Чтение числовых констант

Чтение текста на диске компьютера имеет гораздо больше "подводных камней", чем запись. Рассмотрим чтение числовых констант; символы и строки читаются совсем иначе.

Для чтения числовых констант удобно пользоваться процедурой read — ее выполнение для текстов весьма отличается от чтения типизированных файлов. Ее вызов имеет вид

read(f, список_имен_переменных);,

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

Целая константа — это последовательность цифр, возможно, со знаком '+' или '-' в начале, которая задает целое число соответствующего целого типа, причем между знаком и первой цифрой в тексте не может быть пробелов, например, 0, -25, +144.

Действительная константа — это последовательность цифр и других символов со структурой констант языка Delphi, например, l.l, 0.99, 1e-3, -2.73E+02.

Числовые константы в текстах отделяются пробелами в произвольном количестве. Символы табуляции и конца строки также называются пробелами.

Вызов read(f, X), где X — имя целой или действительной переменной, выполняется так. Из текста читаются пробелы, а затем символы константы до ближайшего пробела. Доступным после чтения константы будет первый пробел после нее. Если символы образуют константу нужного типа, то по ним вычисляется значение и присваивается переменной. При действительной переменной X в тексте может быть и целая константа — по ней вычисляется действительное значение.

Символы могут не образовывать константу соответствующего типа — тогда возникает ошибочная ситуация и выполнение программы аварийно завершается. Например, ошибочными являются последовательности символов "- 2" (пробел между знаком и цифрой), "12345m", "123-" (присутствуют нецифровые символы там, где их не может быть) или "13.", если читается значение целой переменной.

Если доступен конец файла, то попытка читать число не завершается аварийно, а соответствующая переменная получает значение 0!

Чтение констант базовых типов по процедуре readln аналогично процедуре read. Отличие в том, что после чтения последней константы все символы текста, оставшиеся до ближайшего <еоl>, пропускаются вместе с ним. Доступным становится первый символ следующей строки текста. Список имен переменных может быть пустым — тогда readln(f) пропускает текущую строку текста. Например, предположим, что в тексте f записаны такие символы.

1

2

3

<eol>

5

5

<chr(26)>

Пусть x, у, z, t — имена целых переменных. После вызовов

read(f,x,у);

read(f,z,t);

они получат значения 1, 2, 3, 55 соответственно, после

readln(f,x,у);

read(f,z,t);

— 1, 2, 55, 0, а после

readln(f,x);

readln(f,y,z,t);

— 1, 55, 0, 0.

Чтение числовой последовательности, записанной в тексте, можно описать с помощью функции eof в цикле следующего вида.

while not eof(f) do

  begin 

   read(f,v);

   обработка значения переменной v 

 end;

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

Чтение в цикле происходит после того, как из вызова eof возвратилось значение false, т.е. каждому чтению предшествует проверка, не прочитан ли файл. Если файл пуст, то первое же выполнение вызова eof(f) порождает true, и тело цикла не выполняется ни разу. Переменная v остается со старым значением, что чревато непредвиденными ошибками.

2.4. Особенности чтения символов и строк

При выполнении вызова read(f, X) переменной X типа char присваивается доступный символ текста, каким бы он ни был, а доступным становится следующий за ним. Исключение — если доступен конец файла, то X получает значение <chr(26)>, но он же остается доступным.

Если X строчного типа, то при выполнении read(f, X) символы до ближайшего <eol> читаются и присваиваются элементам строки X; доступным становится <eol>. Если символов текста до <eol> больше, чем умещается в X, то X заполняется до конца, и доступным становится первый символ после прочитанных в X.

Если перед чтением строки X доступен <eol>, то он остается доступным, а значением X становится пустая строка. Поэтому применять процедуру read для чтения строк не рекомендуется.

Особенно опасно применение read при вводе строк в цикле. Если после ввода строки доступным символом станет <eol>, то последующие попытки чтения строк будут давать им значение '' (пустая строка), <eol> будет оставаться доступным и выполнение программы "зациклится". Например, при выполнении цикла вида

while not eof(f) do

 begin

   read(f,x);        {???}

   обработка x

end;

где x — переменная-строка, читаются символы только первой строки текста, а затем конец строки остается доступным "навсегда".

Если при чтении строки доступен конец текста, он также остается доступным, а переменной-строке присваивается пустая строка.

Чтение символов и строк по процедуре readln аналогично процедуре read, но после чтения символов остаток строки текста пропускается, т.е. доступным становится символ, следующий за ближайшим <eol>, поэтому рекомендуется читать строки с помощью процедуры readln.

Если список имен переменных в вызове readln пуст, пропускается текущая строка текста.

Строки многих текстов "умещаются" в переменных типа string. Тогда чтение текста очень просто описать с помощью переменных-строк. Алгоритмы решения многих задач по обработке текстов имеют такой общий вид.

while not eof(f) do

 begin

   readln(f,s);               {s имеет тип string}

   обработка строки s;

 end.

Пример. Написать процедуру копирования текста при условии, что строки текста имеют длину не более 255, а пустые строки или содержащие только пробелы, не копируются.

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

{Процедура копирования текста f в текст g без пустых строк}

procedure cpnonemp(var f,g: textfile);

var s: string;      {текущая строка текста}

   k: integer;     {счетчик позиций}

   emp: boolean;   {признак пустоты}

begin

 while not eof(f) do

   begin

     readln(f, s);

     k:=1;         {обработка строки s}

     emp:=true;

     while (k<=length(s)) and emp do

       if s[k]<>' ' then emp:=false 

                    else k:=k+l;

     if not emp then writeln(g, s)

   end

end;

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

Выводы

  1.  Файл – именованная область памяти на внешнем носителе, предназначенная для хранения данных. Файл может быть входным или выходным. В языке предусмотрено два способа доступа к компонентам файла: последовательный и произвольный (прямой).
  2.  Для организации эффективной и удобной для пользователя работы с файлами в языке предусмотрен ряд процедур и функций. Процедуры осуществляют все необходимые действия по организации файлов и доступу к компонентам файлов. Функции выполняют дополнительные действия, облегчающие программисту обслуживание уже существующих файлов.
  3.  При работе с файлами выделяются ряд этапов, организуемых, как правило, в виде отдельных процедур: организация файла, доступ к компонентам, корректировка и др.


Приложение № 1

ПРОЦЕДУРЫ И ФУНКЦИИ РАБОТЫ С ФАЙЛАМИ

Находятся в модуле System

Procedure Append(var F: Text);

Открывает существующий текстовый файл F для добавления информации в конец файла (дозаписи). Если файл F уже открыт, он закрывается и вновь открывается. Текущая позиция файла устанавливается к концу файла. Если внешнего файла с данным именем не существует, происходит ошибка времени выполнения.

Procedure AssignFile(var F; FileName: String);

Сопоставляет имя внешнего файла FileName с файловой переменной F (F - файловая переменная любого файлового типа, FileName - выражение типа String или выражение типа PChar, если допускается расширенный синтаксис). Все дальнейшие операции с F производятся с внешним файлом. Нельзя использовать AssignFile с уже открытой файловой переменной.

Procedure CloseFile(var F);

Разрывает связь между файловой переменной F и внешним дисковым файлом и закрывает файл (F - файловая переменная любого файлового типа, открытая процедурами Reset, Rewrite или Append). Внешний файл, связанный с F, полностью модифицируется и затем закрывается, освобождая дескриптор файла для повторного использования.

Function Eof(var F): Boolean; (типизированные или нетипизированные файлы)

Function Eof[(var F: Text)]: Boolean; (текстовые файлы)

Проверяет, является или нет текущая позиция файла F концом файла. Eof(F) возвращает True, если текущая позиция файла находится за последним символом файла или если файл пуст; иначе, Eof(F) возвращает False.

Procedure Erase(var F);

Удаляет внешний файл, связанный с F (F - файловая переменная любого файлового типа). Перед вызовом процедуры Erase, файл необходимо закрыть.

Function FileSize(var F): Integer;

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

Function FilePos(var F): LongInt;

Возвращает текущую позицию указателя внутри файла F (F - переменная любого файлового типа, кроме типа Text). Перед использованием FilePos, файл должен быть открыт. Функция FilePos не используется с текстовыми файлами.

Procedure Reset(var F [: File; RecSize: Word]);

Открывает существующий внешний файл, ассоциированный с файловой переменной F (F - переменная любого файлового типа, связанного с внешним файлом с помощью AssignFile; RecSize - необязательное выражение, которое используется, если F - нетипизированный файл). Если F - нетипизированный файл, RecSize определяет размер записи, который используется при передаче данных. Если RecSize опущен, заданный по умолчанию размер записи равен 128 байт. Если внешнего файла с таким именем нет, возникает ошибка времени выполнения. Если файл, связанный с F уже открыт, он сначала закрывается и затем вновь открывается. Текущая позиция файла устанавливается к началу файла.

Procedure Rewrite(var F: File [; Recsize: Word]);

Создает и открывает новый внешний файл с именем, связанным с F (F - переменная любого файлового типа, связанного с внешним файлом с использованием AssignFile; RecSize - необязательное выражение, которое используется, если F - нетипизированный файл). Если F - нетипизированный файл, RecSize определяет размер записи, который используется при передаче данных. Если RecSize опущен, заданный по умолчанию размер записи равен 128 байт. Если внешний файл с тем же самым именем уже существует, он удаляется, и создается новый пустой файл.

Procedure Seek(var F; N: LongInt);

Перемещает текущую позицию файла F к определенному компоненту с номером N. Номер первого компонента файла - 0. Процедуру можно использовать только с открытыми типизированными или нетипизированными файлами. Инструкция Seek(F, FileSize(F)) перемещает текущую позицию файла в конец файла.

Function Eoln[(var F: Text)]: Boolean;

Проверяет, является ли текущая позиция файла концом строки текстового файла. Eoln(F) возвращает True, если текущая позиция файла - в конце строки или файла; иначе Eoln(F) возвращает False.

Procedure Read(F, V1 [, V2, ..., Vn]); (типизированные и нетипизированные файлы)

Procedure Read([var F: Text;] V1 [, V2, ..., Vn]); (текстовые файлы)

Для типизированных файлов процедура читает компонент файла в переменную. При каждом считывании текущая позиция в файле продвигается к следующему элементу. Для текстовых файлов читается одно или несколько значений в одну или несколько переменных. С переменными типа String Read считывает все символы вплоть до следующей метки конца строки (но не включая ее), или пока функция Eof(F) не примет значение True. Переменной присваивается получившаяся в результате символьная строка. В случае переменной целого или вещественного типа процедура ожидает поступления последовательности символов, образующих число по правилам синтаксиса языка Delphi. Считывание прекращается при обнаружении первого пробела, символа табуляции или метки конца строки, или в том случае, если функция Eof(F) принимает значение True. Если числовая строка не соответствует ожидаемому формату, то происходит ошибка ввода-вывода.

Procedure Readln([var F: Text;] V1 [, V2, ..., Vn]);

Является расширением процедуры Read и определена для текстовых файлов. Считывает строку символов в файле (включая маркер конца строки) и переходит к началу следующей строки. Вызов функции Readln(F) без параметров приводит к перемещению текущей позиции файла на начало следующей строки, если она имеется, в противном случае происходит переход к концу файла.

Function SeekEof[(var F: Text)]: Boolean;

Возвращает признак конца файла и может использоваться только для открытых текстовых файлов. Обычно применяется для считывания числовых значений из текстовых файлов.

Function SeekEoln[(var F: Text)]: Boolean;

Возвращает признак конца строки в файле и может использоваться только для открытых текстовых файлов. Обычно применяется для считывания числовых значений из текстовых файлов.

Procedure Write([var F: Text;] P1 [, P2, ..., Pn]); (текстовые файлы)

Записывает одну или более величин в текстовый файл. Каждый параметр записи должен иметь тип Char, один из целочисленных типов (Byte, ShortInt, Word, LongInt, Cardinal), один из типов с плавающей запятой (Single, Real, Double, Extended, Currency), один из строковых типов (PChar, AnsiString, ShortString), или одного из логических типов (Boolean, Bool).

Procedure Write(F, V1, ..., Vn); (типизированные файлы)

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

Procedure Writeln([var F: Text;] P1 [, P2, ..., Pn]); (текстовые файлы)

Выполняет операцию Write, затем помещает метку конца строки в файл. Вызов Writeln(F) без параметров записывает в файл маркер конца строки. Файл должен быть открыт для вывода.


 

А также другие работы, которые могут Вас заинтересовать

39533. Приборы СВЧ и оптического диапазона 184 KB
  Требуется определить как надо изменить другой параметр чтобы получить ту же выходную мощность или как при этом изменится режим усилителя. Во сколько раз надо изменить мощность возбуждения чтобы выходная мощность осталась неизменной Решение: см. найдём отношение: Поскольку сначала до изменения параметров клистрон работал в оптимальном режиме то по графику определяем : Электронная мощность изменяется при изменении тока и напряжения . Но параметры не изменяются при условиях задачи а мощность возбуждения значит результат...
39534. Аудит показателей бухгалтерского баланса в соответствии с МСФО 451.5 KB
  Трудности возникают и из-за несовпадения временных периодов, а также методики учета по окончании периода. Это связано с тем, что и в той и другой системах предусмотрено применение различных отчетных периодов, различных способов закрытия счета и т. д. При этом приходится закрывать счета в каждой базе данных.
39535. Математическое программирование (ЛИНЕЙНОЕ ПРОГРАММИРОВАНИЕ) 2.42 MB
  Различные формы модели задачи линейного программирования . Формулировка основной задачи линейного программирования . Понятие допустимого решения области допустимых решений оптимального решения задачи линейного программирования . Переход от задачи минимизации целевой функции к задаче максимизации .
39536. Двухэтажный жилой дом с гаражом 212.13 KB
  Условия организации и осуществления строительства Жилое двухэтажное здание с гаражом находится в районе города Луганск который относится к 1 климатическому району.56 Кладка внутренних стен при высоте этажа до 4 м.03 V=FF Кладка перегородок толщиной в 1:2 кирпича при высоте этажа до 4 м.
39537. Экстраполяция трендов. Модель спрос-предложение 86.28 KB
  Постановочный этап: определяются конечные цели исследования моделирования набор участвующих в модели факторов и показателей и их роли. 3 Этап параметризации и спецификации модели: собственно моделирование то есть выбор вида модели функции регрессии в том числе состава и формы входящих в нее связей между переменными. 5 Этап идентификации модели: статистическое оценивание неизвестных параметров модели по собранным данным статистический анализ модели. 6 Этап верификации модели: сопоставление фактических реальных данных и...
39538. РАЗРАБОТКА ПРОГРАММЫ РАСПРЕДЕЛЕНИЯ ДОКУМЕНТООБОРОТА В МНОГОПРОФИЛЬНОМ ОАО 1.47 MB
  Делопроизводство - это термин, используемый в конторской практике для набора правил работы с документами. Есть системы документооборота, которые настраиваются на правила делопроизводства. Есть системы, которые изначально ставят своей целью выполнение именно этих правил и содержат более общие функции в достаточной мере, чтобы их назвали системами документооборота.
39539. Разработка мероприятий по повышению финансовых результатов деятельности ООО «ПАРИТЕТ ПЛЮС» 641.96 KB
  Об абстрактности и конкретности философии государства и права. Попытки создать философию права как некую универсальную и всеобщую конструкцию исходящую из каких бы то ни было оснований антропологического материализма объективного или субъективного идеализма экзистенциализма или позитивизма на протяжении более чем двух столетий в Европе и России оказались несостоятельными. Оказалась не более чем иллюзией и сознательно разработанным мифом попытка представить право и полный свод правильных законов как способ решить все основные задачи по...
39540. Разработка методики проектирования и изготовления малошовной плетеной одежды с триаксиальной структурой, иммитирующей ткань «Шанель» 4.56 MB
  Сейчас получили распространение технические ткани с трехниточной структурой в которых все нити одного наклонного застила располагаются поверх нитей другого наклонного застила не образуя переплетения рисунок 1. Второй вид расположения нитей застилов отличается от наложения тем что нити одного из застилов попеременно располагаются под и над нитями другого застила рисунок 1. Третьим видом расположения нитей застилов является полотняное переплетение рисунок 1. а б...
39541. Гражданско-правовая характеристика и практическое применение гражданско-правовых норм касающихся недействительных сделок 337 KB
  В 1 главе рассматриваются понятие и основания недействительности сделок, рассматриваются понятия ничтожности и оспоримости сделки, а также основания недействительности части сделки. Во 2 главе дается характеристика различных пороков сделок. В 3 главе – правовые последствия признания сделок недействительными. В каждой главе приводятся примеры из судебной практики.