Смекни!
smekni.com

Паскаль робота з файлами (стр. 2 из 4)

FAF = fileof FA {???}.

2. Послідовний запис у типізовані файли

Перш, ніж записувати в файл, слід відкрити його для запису. Це задається процедурою REWRITE. Після виклику ReWrite(f) значення f подається як (<>, 0, W), тобто незалежно від попереднього значення f послідовність у файловій змінній стає порожньою:

F
­ стан W

Значення 0 вказівника доступного елемента свідчить про те, що можна записати нове значення в перший, тобто з номером 0, елемент файла. Ця процедура викликається для створення нового файла або поновлення старого зі знищенням даних, що були в ньому. Після її виконання файл називається встановленим у початковий стан для запису.

Запис у файл задається процедурою WRITE. При виконанні її виклику

write ( f, вираз-типу-компонентів-файла)

обчислюється значення виразу та присвоюється доступному елементу файла, після чого вказівник доступного елемента зсувається на 1 елемент. Наприклад, після виконання останього з наведених операторів у програмі

program ...

var f : file of integer; x : integer

begin ...

rewrite(f); x:=2;

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

...

end.

файлова змінна f має значення, що подається як (<1, 2, 4>, 3, W).

Узагалі, значення (<f0 , … , fn-1>, n, W) файлової змінної f при виконанні write(f, вираз) міняється на (<f0, … , 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 не можна застосовувати до типізованих файлів. Вона призначена лише для роботи з текстами.

Приклад 13.1. Треба створити файл із такими даними про студентів групи: прізвище та ім’ я студента, а також середній бал його успішності.

Дані про студента можна подати записом типу

Student = record

SName, Name : string[20];

Ball : real

end.

Зв’ язування та встановлення файла в початковий стан для запису оформимо процедурою OpenFile, а створення – процедурою CreatFile у такій програмі:

program InPutGroup;

type

Student = record

Sname, Name : string[20];

Ball : real;

end;

var

Fi : file of Student; { Файлова змінна Fi – інформаційний файл }

FileName: string; { Змінна для введення імені файла }

procedure OpenFile;

begin

writeln('Задайте ім''я файла, що буде створюватися: ');

readln(FileName);

assign(Fi, FileName);

rewrite(Fi);

end;

procedure InPutFile;

var St : Student;

Ch : char;

begin

repeat

writeln('Задайте дані про студента:');

write('Прізвище>'); readln(St.SName);

write('Ім''я>'); readln(St.Name);

write('Середній бал успішності>'); readln(St.Ball);

write(Fi, St); {***}

write('Чи треба вводити дані про нового студента? "Y"/"N"> ');

readln(Ch);

until (Ch = 'n') or (Ch = 'N');

close(Fi);

end;

begin

writeln('Програма створення файла даних про успішність');

openfile; { Виклик процедури відкривання файла }

creatfile; { Виклик процедури створення файла }

end.

3. Послідовне читання типізованих файлів

Для того, щоб читати вже створений типізований файл, треба відкрити його для читання викликом процедури RESET(f). Після її виклику файлова змінна установлюється в початковий стан для читання, а номером доступного елемента стає 0 незалежно від того, чи є взагалі елементи в файлі. Значення f можна подати як (F, 0, R), тобто

F f0 f1 ...
­ Стан 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<n у значенні файлової змінної (<f0, … , fn-1>, i, R). Значення true повертається за i=n, що можливо після читання всіх елементів файла без установлення його в початковий стан.

Виклик функції eof дозволяє визначити, чи є ще у файлі непрочитані елементи, та запобігти читання з вичерпаного файла.

Практично завжди програму варто записувати так, щоб у процесі її виконання перевірка невичерпаності файла передувала виклику процедури read.

Приклад 2. Напишемо програму обчислення середнього арифметичного A цілих чисел непорожнього файла nums.dat та запису в інший файл всіх його чисел, менших A.

Розв'яжемо задачу в такий спосіб:

1) прочитати всі числа з файла, обчислити їх суму й кількість і визначити A;

2. повторно прочитати всі числа, копіюючи з них лише менші від A.

Нехай числа записано в файлі цілих з ім'ям nums.dat, а числа, менші за середнє, переписуються в файл littls.dat. Наведені дії задаються програмою

program numbers;

var f , g : fileof integer;

v : integer; a : real;

n : integer;

begin

assign ( f, 'nums.dat' );

{1}reset ( f );

read ( f, v ); {читання першого елемента без перевірки !}

a:=v; n := 1;

whilenot 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);

whilenot eof ( f ) do

begin

read ( f, v ); if v < a then write(g, v )

end;

close ( f ); close(g);

end.

Як бачимо, читання першого елемента задано без перевірки, чи можна взагалі його прочитати. У разі порожнього файла виконання програми завершується аварійно.

Приклад 3. Вивести на екран комп’ ютера дані про студентів з файла, створеного за програмою з прикладу 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 : fileof 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);{Вихід із програми}