Робота з файлами (Паскаль та Бейсік), Відкритий клас
Назва документа: Любутов О.Д. Вирішення олімпіадних завдань
Анотація: Олімпіадні завдання з програмування
Робота з файлами
Зараз практично у всіх олімпіадних завдань введення (виведення) даних здійснюється з файлу (у файл). Всі ми знаємо, що файл називається область даних на носії, що має власне ім'я. Окрім імені файл має ще й довжину. Якщо довжина файлу N байтів, файл - це просто N байтів, розташованих на носії.
У різних мовах програмування прийнято різну класифікацію файлів. У паскалі це типизований файл, нетипізований файл та текстовий файл. У бейсику файли поділяються на файли прямого доступу (аналог типизованих) та файли послідовного доступу. Чим вони відрізняються один від одного? Самі файли – нічим. Відрізняється спосіб інтерпретації даних.
Будь-який існуючий файл можна відкрити як файл прямого доступу або як послідовного.
Файлпослідовного доступускладається (має складатися) з рядків (кілька байтів) які закінчуються спеціальною ознакою (зазвичай це символи повернення каретки і перекладу рядка, їх ASCIIкоды 13 і 10).
Таким чином, якщо ми відкрили для читання файл (як файл послідовного доступу) і намагаємося прочитати дані, наприклад, в рядкову змінну, то в результаті в змінній виявиться записана послідовність символів до першого ознаки кінця рядка, що зустрівся. При наступній спробі читання будуть лічені символи до наступного кінця рядка. І так далі до кінця файлу.
Працюючи з файломпрямого доступуми працюємо з файлом просто як із одновимірним масивом блоків байтів. Ми можемо визначити розмір блоку, яким вибиратимемо дані з файлу. Причому при роботі з масивом ми можемо звертатися до довільногоблоку байтів.
І навпаки. Файли прямого доступу дозволяють здійснювати дуже швидкий доступом до інформації, але якщо ця інформація розбита на частини рівного розміру.
Давайте подивимося, як практично здійснюється робота з файлами. Почнемо із файлів послідовного доступу.
Для роботи з файлом його потрібно «відкрити», а по закінченні роботи «закрити». Для цього в бейсику існують оператори OPEN і CLOSE. Ось їх формат:
- це шлях та ім'я файлу (якщо шлях не вказаний, то програма шукатиме файл у папці, звідки запущено проект або відкомпільована програма)
- одне із зарезервованих слів:
INPUT – існуючий файл відкривається для читання. Необхідно, щоб файл із таким ім'ям існував.
OUTPUT – створюється порожній файл із заданим ім'ям. Якщо файл з таким ім'ям існував до цього, він затирається новоствореним.
APPEND – існуючий файл відкривається для запису. Тобто все що ми запишемо, буде розташовуватися після інформації, що вже є у файлі.
- просто число, яке надалі використовуватиметься для ідентифікації файла.
Між операторами OPEN і CLOSE ми можемо працювати з відкритим файлом. Читати з нього, писати чи дописувати до нього. Ось як це реалізується. Допусти ми хочемо створити файл proba.txt в корені на диску C. І записати в нього перший двовірш вірша Некрасова і числа від 1 до 10.
DIM S as string, I as integer
OPEN “C:\proba.txt” FOR OUTPUT AS #1
S=”Одного разу, в зимову студію”
PRINT #1, "Я з лісу";
PRINT #1, "вийшов, був сильний мороз"
IF I ) повертає логічне значення True, якщо досягнуто кінець файлу. Наприклад, нам потрібно вивести на екран весь вміст текстового файлу:
DIM S as string
OPEN “C:\proba.txt” FOR INPUT AS #1
DO WHILE NOT EOF(1)
Про файли послідовного доступу, мабуть, все.
Тепер розберемо роботу із файлами прямого доступу. Тут розмір блоку інформації, з якою ми працюватимемо, залишається суворо фіксованим. Тому ми зможемо звернутися до потрібного блоку (до потрібного запису).
Реалізується це так:
Open "C:\proba.txt" For Random As #1 Len = 2
У цьому рядку відкривається файл прямого доступу (про це говорить службове слово Len), на диску C, з ім'ям proba. txt по першому каналу ідовжиною записурівною двом байтам. Якщо файл proba. txt існує на диску С, то операції читання або запису будуть проводитися з ним, інакше буде створено файл з таким ім'ям.
Читання та запис здійснюється спеціальними операторами:
Номер запису у бейсику починається з одиниці.
І завершується робота із файлом оператором CLOSE #1
Насамперед необхідно оголосити файлову змінну, розмір якої визначатиме розмір запису.
FileVar:file ofтип ;
var F: File of byte;
Для переміщення записів у паскалі використовується процедураseek( , ). У паскалі записи починаються з нульового запису.
Решта відбувається так само як з текстовими файлами.
Потрібно зв'язати файлову змінну з конкретним файлом:
Assign(F, 'З :\proba.txt');
Потім відкрити файл:
Тепер можна прочитати з файлу 20 символів, починаючи з 25 символу і вивести їх на екран:
for i:= 25 to 44 do
І не забудемо закрити файл:
А тепер спробуємо розглянути олімпіадну задачу, де було задано файл з 999999 чисел, що не перевищують за модулем 1000000000 (по 4 байти на число). Потрібно було знайтимедіану цього числового масиву. Медіаною масиву називається число, розташоване в середині впорядкованого масиву. У нашому випадку медіаною буде значення 500 000 елемента в упорядкованому масиві.
Так як завдання реалізовувалася DOS-івськими мовами програмування (BP 7.0 QB і т.д.), де обсяг пам'яті обмежений 64Кб (якщо не використовувати динамічну пам'ять), то зрозуміло, що розмістити весь файл в оперативній пам'яті (4Мб) не представляється можливим . Можна придумати багато різних способів розв'язання цієї задачі, і залежно від продуктивності комп'ютера вони або покладуться в обмеження часу виконання (30 секунд), або ні. Але найбільш оптимальним способом вирішення цього завдання буде робота з даними у файлі.
Для знаходження медіани масиву нам зовсім не обов'язково відсортувати масив. Спробуємо знайти посадкове місце (індекс елемента в відсортованому масиві) першого елемента. Для цього порівнюватимемо наш елемент по черзі з кожним елементом масиву, починаючи з останнього. Якщо наш елемент не більший за останній, то порівнюємо його з передостаннім. Якщо не більше передостаннього, то порівнюємо з передостаннім, і так далі, доки не знайдеться елемент, який буде меншим за наш. Тоді ми міняємо місцями наш елемент та той, який менший. А потім починаємо порівнювати наш елемент з наступним, що стоїть за тим, який ми обміняли з нашим. Щоб було зрозуміліше, розглянемо на числах:
Ми хочемо знайти «посадкове місце» першого елемента нашого масиву