Послідовне читання типізованих файлів
Для того, щоб читати вже створений типізований файл, треба відкрити його для читання викликом процедури RESET(f). Після її виклику файлова змінна установлюється в початковий стан для читання, а номером доступного елемента стає 0 незалежно від того, чи є взагалі елементи в файлі. Значення f можна подати як (F, 0, R), тобто
Ff0f1...
¬ СтанR
Якщо F є порожньою послідовністю, F=<>, то спроба читання з файла завершується аварійно, оскільки доступного елемента просто немає!
Файл із диску можна читати тільки після установлення файлової змінної в початковий стан для читання, тобто установлення обов’ язкове. Можливість чи заборона установлення файлової змінної, зв’ язаної з клавіатурою, залежить від системи програмування. У системі Турбо Паскаль таке установлення можливе, хоча й не обов’ язкове.
Зазначимо, що в програмі може бути довільна кількість викликів процедури reset, і що система Турбо Паскаль дозволяє після виконання її викликів не тільки читати з файла, а й записувати в нього, тобто змінювати його перший елемент. І взагалі, система дозволяє змінювати за допомогою write доступний елемент файла, яким би не було його місце в послідовності і за будь-якого стану файла.
Читання доступного елемента файла задається процедурою READ. Її виклик має вигляд
read(f, 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 = <>). За такого значення i виклик read призводить до аварійного завершення програми.
У виклику процедури read можна вказувати довільну кількість аргументів, що є іменами однотипних змінних:
read ( f, v1, v2, … , vN ).
Такий виклик виконується насправді як послідовність викликів
read(f, v1 ); read(f, v2 ); ... read(f, vN ).
Зрозуміло, треба гарантувати при цьому, що в файлі залишилося достатньо непрочитаних елементів.
Підкреслимо, що до типізованих файлів незастосовна процедура читання readln – її можна вживати лише для читання текстів.
Визначення того, чи прочитано вже файл, задається функцією EOF. За виклику eof(f) повертається бульове значення false, якщо доступний який-небудь елемент файла, тобто значення виразу i
Виклик функції eof дозволяє визначити, чи є ще у файлі непрочитані елементи, та запобігти читання з вичерпаного файла.
Практично завжди програму варто записувати так, щоб у процесі її виконання перевірка невичерпаності файла передувала виклику процедури read.
Приклад 1. Напишемо програму обчислення середнього арифметичного A цілих чисел непорожнього файла nums.dat та запису в інший файл всіх його чисел, менших A.
Розв'яжемо задачу в такий спосіб:
1) прочитати всі числа з файла, обчислити їх суму й кількість і визначити A;
2.повторно прочитати всі числа, копіюючи з них лише менші від A.
Нехай числа записано в файлі цілих з ім'ям nums.dat, а числа, менші за середнє, переписуються в файл littls.dat. Наведені дії задаються програмою
program numbers;
var f , g : file of integer;
v : integer; a : real;
n : integer;
begin
assign ( f, 'nums.dat' );
{1}reset ( f );
read ( f, v ); {читання першого елемента без перевірки !}
a:=v; n := 1;
while not eof ( f ) do
begin {з виклику eof(f) повернулося false,}
{тому можна читати доступний елемент}
read ( f, v );
a := a + v; n := n + 1
end;
{з виклику eof(f) повернулося true}
a := a/n;
{2}reset ( f );
assign(g, 'littls.dat'); rewrite(g);
while not eof ( f ) do
begin
read ( f, v ); if v < a then write(g, v )
end;
close ( f ); close(g);
end.
Як бачимо, читання першого елемента задано без перевірки, чи можна взагалі його прочитати. У разі порожнього файла виконання програми завершується аварійно.
Приклад 2. Вивести на екран комп’ ютера дані про студентів з файла, створеного за програмою з прикладу 13.1.Природньо розглядати файл як послідовність записів типу Student. Його елементи по одному читаються в допоміжну змінну St та значення її полів (прізвище, ім’ я й середній бал), що мають базовий тип або є рядками, виводяться на екран із його попереднім очищенням. Очищення екрану задається викликом процедури CLRSCR, що входить до складу модуля Crt. Після кожного виведення для одержання нових даних слід натиснути на клавішу Enter.
У наступній програмі використовується змінна IOResult, означена в модулі Dos. Вона набуває ненульового значення, якщо при виконанні процедури Reset виникла якась помилка, наприклад, зв’ язана з тим, що користувач задав ім’ я неіснуючого файла. Перед її викликом вимикається режим перевірки правильності введення-виведення, оскільки в цьому режимі за помилкового виконання Reset програма аварійно завершується. Після виклику Reset режим перевірки вмикається знов.
program OutPutGroup;
uses Crt, Dos; { Підключення модулів Crt та Dos }
type Student = record
Sname, Name : string[20]; Ball : real;
end;
var Fi : file of Student;
FileName: string; { Змінна для введення імені файла }
procedure OpenFile;
var Rez : Integer; Ch : char;
begin
Rez:=1;
while Rez <> 0 do { Rez=0 – ознака того, що введено} {правильне зовнішнє ім’я файла}
begin
writeln('Задайте ім''я файла'); readln(FileName);
assign(Fi, FileName);
{$I-} {Вимкнення контролю правильності читання/запису}
reset(Fi);
{$I+} { Увімкнення контролю }
Rez:=IOResult;
if Rez <> 0 then
begin
writeln('Перевірте правільность імені файла !');
writeln('Чи буде повторне задання імені? "Y"/"N":');
readln(Ch);
if (Ch = 'n') or (Ch = 'N') then halt(0);{Вихід із програми}
end;
end;
end;
procedure OutPutFile;
var St : Student; Ch : char;
begin
writeLn('Чи бажаєте дивитися дані про студентів ? "Y"/"N" ');
readln(Ch);
if (Ch = 'Y') or (Ch = 'y') then
begin
while not eof(Fi) do
begin
read(Fi, St); clrscr;
writeln('Прізвище : ', St.SName);
writeln('Ім''я: ', St.Name);
writeln('Середній бал: ', St.Ball);
readln;
end;
end;
close(Fi);
end;
begin
clrscr; writeln('Програма друкування даних про студентів');
openfile; outPutfile;
end.