Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
часть4 .doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
288.77 Кб
Скачать

що по суті відкриває канали введення-виведення. В ТР можна, не вагаючись, опустити program. Oпеpaтоp read та readln - це оператори введення інформації. Їх аргументами повинні-бути списки змінних, значення яких будуть зчитані. Тип змінних при введенні із текстового файлу може бути тільки цілим, дійсним, символьним, рядковим або сумісним з ними.

Складні, структуровані типи можуть бути введені тільки по-елементно, або по полям для запису.

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

-Початок рядка йде відразу за останнім введеним до цього символом;

-Зчитується кількість символів, рівне об'явленій довжині рядка;

Але якщо під час зчитування зустрівся символ з кодом #13, то читання рядку припиняється. Сам символ #13 вважається розділювачем рядків і в змінну ніколи не зчитується. При введенні з клавіатури особливої різниці між read та readln немає. Процедура readln зчитує значення поточного рядка і переводить позицію на початок наступного рядка, навіть якщо в поточному рядку залишилися не прочитані дані. Виклик readln (f) зовсім пропустить рядок в файлі, a readln без вказівника в файлі зробить паузу до натискання клавіші введення. Символ #26 також являється розділювачем і обмежує рядок, але за ним зчитування вже неможливе, файл на цьому закінчується.

Оператори write і writeln виводять значення х, або список значень XI,Х2 ,...Хn в текстовий файл f. (Якщо файл не вказаний, то вважається, що виведення направлене в файл OUTPUT).

Значення, при виведенні, можуть мати лише цілі, дійсні, символьні, рядкові типи, а також похідні від них. Всі можливі структури (записи, масиви) повинні виводитись по їх полям або по елементам. Множини, вказівники., або файли змінних також не можуть бути виведені без попереднього їх перетворення в складові, що виводяться. Виключення -тільки тип Boolean.

Приклад:

Const x: boolean =tme;

у: boolean =false;

........................

write (x, '... ',y);

Оператор write виводить на екран true...false. Ці значення прочитати із файлу в такому вигляді не можна. Щоб одержати із файла логічне значення, необхідно закодувати його: 0-false, і-true, зчитати в байтову змінну, а потім перетворити в логічне значення.

Var by:Byte;

boo: Boolean absolute by;

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

Read(by);

Процедура write виводить дані в поточний рядок і не зачиняє його, тобто

наступні дані запишуться в той же рядок.

Формально в зовнішньому файлі розмір рядка не обмежений. Виключення - виведення на дисплей.

Процедура writeln виводить рядок даних і закриває його, переписує

символ #13 в його кінець. Це автоматично відкриває наступний рядок, а на екрані повертає курсор в крайню ліву позицію і опускає його на рядок вниз.

Оператори write(f) або writeln(f), де f - ім'я логічного файлу, даний без списку виведення, створює пустий рядок, що має один тільки признак кінця рядка.

Існує можливість керування форматом виведення даних. Можна вказати формат, а саме створити поле для розміщення цих значень. Формати мають зміст тільки при роботі з текстовими файлами. У всіх інших випадках вони не застосовуються.

Задача: Написати програму, яка дописує літеру с в кінець тексту t.

uses crt;

type tekst=file of char;

var t:tekst;

sv:char;

begin

assign(t,’a.dat’);

append(t);

write(t,’c’);

close(t);

reset(t);

while not EOF (t) do

begin

read(t,sv);

write(sv);

end;

close(t);

end.

Задача: Type Текст = file of char

Описати процедуру, яка записує в тексті t тільки перше входження кожної літери.

Uses crt;

Type

Text=file of char; m=array [-1..50] of char;

var

f :text;

s:set of char;

mas:m;

sim:char;

i:integer;

procedure x(var m1:m);

begin

clrscr;

reset(f);

while not (eof(f)) do

begin read(sim);

if sim in s then writeln(‘ ’)

else begin

write(sim);

s:=s+[sim];

end; end; end;

begin

assign(f,’sss.dat’);

rewrite(f);

writeln(‘enter the text’);

for i:=1 to 10 do

begin

read(mas[i]);

write(f,mas[i]);

end;

close(f);

s:=[];

x(mas);

readln;

end.

ТИПІЗОВАНІ (КОМПОНЕНТНІ) ФАЙЛИ.

Це файли з об'явленим типом його компонентів, тобто файл з набором даних однієї і тієї ж структури. Об'ява такого типу файлу має наступний вигляд:

File оf<тип_компонентів>;

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

Assign(FP, 'P.DAT');

Reset(FP);

.................................

Rewrite(FP);

Для типізованих файлів обидві процедури Reset та Rewrite встановлюють режим зчитування-запису у відповідності із значенням попередньо визначеної системної змінної FileMode. Вона по замовчанню рівна двом, тобто незалежно від вибору процедури відкриття, файл відкривається і для читання, і для запису. Це вірно лише для типізованих і безтипових файлів. Цей порядок порушується, якщо значення FileMode відповідає режиму тільки запису (1), або тільки читання (0). Змінити режим можна простим присвоюванням потрібного значення змінній FileMode перед відкриттям файлу. Після цього виклик Reset буде відкривати файл у заданому режимі, навіть якщо він буде тільки режиму запису.

Після відкриття файлу введення-виведення даних здійснюється

стандартними операторами:

Read(f,x); Write(f,x);

Першим аргументом повинне бути ім'я логічного файлу з яким зв'язаний "конкретний фізичний файл. Далі повинна стояти змінна або їх список того ж типу, що і об'явлений тип компонентів файлу, в яку записується чергове значення із файлу при читанні, чи навпаки - яка записується в файл. На відміну від файлів типу text, типізовані файли мають більш строгу внутрішню структуру. При запису в них записується машинне представлення чергового компоненту будь-то число, масив або запис. В середині файлу компоненти не відділяються нічим один від одного (але всеодно знайти компонент нескладно : кожен з них займає в файлі однаковий об'єм, що дорівнює його розміру). Тому не має сенсу застосовувати до типізованих файлів оператори readln та writeln. В них просто не існує такого поняття як рядок і його кінець, і не має признаку кінця файлу (кінець визначається довжиною файлу). Навіть, якщо об'явити файл як:

Var f:file of string[80];

він не буде схожий на файл текстів та рядків. В ньому як і раніше не буде символів кінця рядка, а буде (після запису) суцільна послідовність символів, кратна 81. Гірше того, якщо реальне значення рядка менше 80 символів, то всеодно в файлі виявиться по 81 символу на рядок, а надлишок буде забитий сміттям. Тому, любі спроби трактувати типізований файл, як текстовий, особливо спроби вивести його на екран, викличуть помилку.

Для спеціальних цілей (написання програм перекодування тексту) можна представляти текстові файли як file of char. Це не оживить процедур readln та writeln, а також функції EOLN, що працюють з текстами, але при додержуванні недоторканості і не змінності кодів кінця рядка і кінця файлу дасть можливість побуквенного читання, зміни і послідуючого

запису в інший file of char вихідного тексту (щоб не закладати імена текстових файлів в текст самої програми, слідувало б використовувати функцію ParamStr).

Переваги типізованих файлів :

- Вони максимально ефективним способом характеризують числову інформацію;

- Дозволяють зчитувати і записувати складні і громіздкі структури буквально однією командою.

Наприклад:

Туре

Dim_20*1OO=array[1..20,1..100]of real;

Var xx, yy: dim_20* 100;

F:file of dim_20xlOO;

Begin

Reset(f);

read(f,xx); {відкриває файл і зчитує відразу весь масив}

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

write (f,yy); {записує відразу весь масив}

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

end.

Масив чисел yy буде записаний в файлі як один елемент. Якщо записано файл масивів, то в нього не можна записати окреме число (як і не можна прочитати одне число).

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

Безтипові файли.

Стандарт ТР вводить особливий файловий тип, який являється по суті

узагальненим файловим типом. Позначення складається тільки зі слова

file без вказування типу компонентів.

Безтиповий тип - це дуже потужний засіб роботи з файлами, так як він

дозволяє маніпулювати з даними не замислюючись про їх типи. З його

допомогою, можна записувати на диск довільні ділянки робочої пам'яті,

та зчитувати їх в пам'ять диску. Можливо перетворювати дані, які

зчитуються із безтипового файлу в любий формат засобом приведення

типів.

Введення-виведення у безтипові файли здійснюється спеціальними

процедурами:

BlockRead та BlockWrite.

Крім того розширюється синтаксис процедур

Reset і Rewrite. В решті принципи роботи залишаються ті ж самі, як і

при роботі з типізованими файлами. Перед використанням файлова

змінна повинна бути зв'язана з конкретним фізичним файлом через виклик оператора Assign. Файл повинен бути відкритим для читання або запису за допомогою виклику процедури Reset(f) і Rewrite(f). Після закінчення роботи файл повинен бути закритим процедурою Close. Відкриваючи безтиповий файл для роботи, користувач неявно встановлює розмір буферу передачі даних, який дорівнює 128 байтів. Однак, можливо явним способом вказати інший розмір буфера (чим він більший, тим швидше проходить введення-виведення), виходячи з ресурсів пам'яті і зручності роботи з даними. Для задання буферу необхідно після оператора Assist відкрити файл розширеним записом процедур:

Reset(Var f:file; BufSize:word);

Rewrite(Var f:file; BufSize:word);

Параметр BufSize задає число байт, зчитаних із файлу за одне звернення до нього, або тих, що записуються в нього. Чим більше значення BufSize, тим швидше проходить обмін даними між носієм файлу (диск) і ОП машини, але тим більша і затрата пам'яті, тому, що саме в пам'яті знаходиться буфер файлу.

Мінімальний блок, який може бути записаний чи прочитаний із файлу -це один байт. Щоб задати його необхідно встановити саме таку величину буфера при відкритті файлу. Максимальний розмір блоку не може перевищувати 64 Кб.

Під час відлагодження програми в ТР можна перевірити розмір буфера, помістивши в вікно перегляду або в вікно аналізу файлову змінну £, що приведена до типу FileRec. (Для цього необхідно підключення модуля DOS)

Для зчитування або запису даних в безтипових файлах застосовувати стандартні процедури Read і Write не рекомендується, їх заміняють процедурами:

BlockRead(Var f:file; VarDestin; count: word[; Readln: word]);

BlockWrite (Var f:file; Vаr Sourse; count: word[; WriteOut: word]);

Ці процедури здійснюють читання в любу змінну Destin і запис із змінної Sourse компонентів файлу, або його рядків чи блоків, що складаються з тієї кількості байтів, яка визначена для буфера файлу f. Якщо count > 1, то за одне звернення буде зчитано count ємностей буферу. Значення count <l не має змісту. Завжди повинна виконуватися умова:

Соипt*Розмір_буферу < 64 Кбайт

Необов'язковий параметр Readin повертає число блоків (буферів), зчитаних поточною операцією BlockRead. Аналогічний параметр WriteOut процедури BlockWrite після кожної операції запису показує число блоків, що записане в даний файл цією операцією.

Якщо операції запису чи читання пройшли успішно, це значить що Readin і WriteOut будуть дорівнювати відповідним значенням параметрів Count, але якщо виник збій при введенні-виведенні і замовлене число блоків не перенеслось, то параметри Readin і WriteOut будуть містити ціле число вдало перенесених блоків (невдача посередині блоку практично рівносильна відміні його читання чи запису). Таким чином, ці параметри можуть використовуватись для контролю виконання операцій BlockRead і BlockWrite.

Приклад:

Var f1,f2:file; {файлові змінні}

Readln, WriteOut: word; {змінні контролю}

Destin, Source: word;

Begin

……………..

BlockRead(fl, Destin, 3, Readln);

If readin 3 then {обробка помилки читання}

…………….

BlockWrite(f2t Source, 4, WriteOut) ;

If WriteOut< > 4 then {обробка помилки запису}

…………….

end.

Якщо при виклику BlockRead останній параметр не вказано, то неможливість зчитати задане число блоків викличе помилку введення-виведення і зупинку програми. Процедури введення-виведення BlockRead і BlockWrite не мають списків введення та виведення, оскільки не визначений тип компонентів файлу. Замість них в викликах присутні безтипові змінні Destin і Source. Адреса початку змінної в пам'яті відповідає адресі пам'яті, починаючи з якої задану кількість байт буде виведено в файл при запису чи вміщено в пам'ять із файлу при читанні. Передаючи змінну процедурі, ми завжди передаємо адресу її змісту, точніше першого байту її значення.

Якщо змінна х масив Var x: array[1..10]of... ,то виклик BlockWrite або BlockRead буде приймати в ній за точку початку відліку блоку перший елемент масиву. Можна більш явно в виклику вказати початок блоку x як х[1]. Але якщо підставляти х[5], то перелік блоку буде вестись уже, починаючи з п'ятого елементу масива.

Особливо обережно треба поводитися зі вказівниками при підстановці їх у BlockWrite і BlockRead. Вказівники повинні бути розіменовані для того, щоб вказувати на дані, а не на місце в пам'яті де зберігається сам вказівник.

Якщо визначений вказівник Р

Type Dim =array[0.. 999] of real;

Var p:^Dim; {вказівник на масив} f:file;

то після створення динамічного масиву Р^, викликом процедури New(p) і його заповнення, він може бути записаний в файл наступним чином:

Assign(f, 'dimfile.dat') ; {зв'язує файли}

Rewrite(f,Sizeof(Dim)); {відкриває файл для читання}

BlockWrite(f,p^ ,1); {записує масив у файл, зсилка р^ розіменована}

Якщо помилково записати р замість р^ то процедура буде працювати, але збережеться у файлі кусок пам'яті, починаючи з Addr(p), який зовсім не дорівнює адресі динамічного масиву Addr(p^). Щоб прочитати згодом записаний масив із файлу, потрібно змінити напрям виведення даних ' (Місце під р повинно бути зарезервовано):

New (р);

Assign(f, 'dimfile.dat');

Reset(f, SizeOf(dim)); {відкриття файлу для читання}

BlockReadln(f, р^ , 1); {читання масиву із файлу}

Close(f);

End.

Перед читанням блоку в динамічну змінну (р^), вона повинна бути коректним чином створена (через виклик New або GetMem, в протилежному випадку наслідки будуть непередбачені). Блочний спосіб роботи з файлами дуже ефективний по часу, і якщо програма використовує великі масиви попередньо обчислювальних констант, то може виявитись більш вигідним винести їх обчислення в іншу програму, котра їх збереже на диску, а в розрахунковій програмі просто встановити, оператори блочного читання вже розрахованих значень. В таких випадках можна навіть виграти на особливостях компілятора ТР. Зазвичай при компіляції програми пам'ять під статичні масиви відводиться в порядку їх слідування в описі. Якщо описані:

Var A,B,C:Array[1..2000] of real;

то їх елементи ставляться в один суцільний ланцюжок.

Addr(B) =Addr(A) +SizeOf(A);

{вказівник на початок об 'єктa в пам 'яті}

Addr(C) =Addr(B)+SizeOf(B);

Це вірно не лише для масивів, але і для любих статичних структур, крім об'єктів: пам'ять в межах блоку опису змінних відводиться послідовно по мірі слідування. Використовуючи цей факт, можна записати або зчитати блоком відразу кілька стуктур даних, прийнявши за початок блоку першу з них:

Assign(f, 'ABC.dat');

Rewrite(f, SizeOf(A)); {відкриває файл та записує в нього 3 блока відразу}

BlockWrite(f,A,3);

Close(f);

End.

Іншою, більш специфічною областю застосування безтипових файлів є робота з системними областями IBM, в тому числі з відеопам'яттю.

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