Задания

Лабораторная работа № 12. Работа с файлами

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

Общие сведения

Файл представляет собой структурированный тип данных, содержащий последовательность компонентов одного типа и одной длины. Число элементов в файле (длина файла) не фиксировано. Это является основным отличием файла от массива.

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

Текстовый файл можно рассматривать как последовательность символов, разбитую на строки длиной от 0 до 256 символов. Для описания используется стандартный тип Text:

Var

F: text;{F - файловая переменная}

Каждая строка завершается маркером конца строки. На практике такой маркер представляет собой последовательность из двух символов: перевод строки chr(13) и возврат каретки chr(10). Эти два символа задают стандартные действия по управлению текстовыми файлами. Открываемые по умолчанию стандартные файлы Input и Output в модуле System имеют тип Text. У текстовых файлов есть своя специфика. Специальные расширения стандартных процедур чтения (Read) и записи (Write) разрешают работать со значениями несимвольного типа. Другими словами, последовательность символов автоматически преобразуется к значению того типа переменной, которая используется в файловых операциях.

Вызов Read(F, Ww), где Ww – переменная типа word, осуществляет чтение из файла F последовательности цифр, которая затем интерпретируется в число, значение которого и будет присвоено переменной Ww. В случае если вместо последовательности цифр идет любая другая последовательность символов, использование такого оператора приводит к ошибке выполнения программы. Открытие текстового файла можно произвести двумя стандартными способами:

- поставить в соответствие файловой переменной имя файла (процедура Assign), открыть новый текстовый файл (процедура Rewrite);

- поставить в соответствие файловой переменной имя файла (процедура Assign), открыть уже существующий файл (процедура Reset).

Текстовый файл в силу своей специфики во время работы допускает только один вид операции: чтение или запись. В связи с этим для работы с текстовыми файлами используется еще одна процедура открытия файла:

Append(vaг F : text);

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

Для обработки текстовых файлов используются процедуры Read и Write, обеспечивающие соответственно чтение и запись одной строки и более в текстовый файл. Использование специальных разделителей строк позволило ввести в состав языковых средств еще две процедуры: Readln, выполняющую те же действия, что и Read, и дополнительно – чтение до маркера конца строки и переход к новой строке; Writeln, обеспечивающую запись всех величин с обязательной установкой маркера конца строки в файл.

Процедура Read обеспечивает ввод данных общим потоком из одной строки, a Readln приводит к обязательному переходу к следующей строке текстового файла, т. е. ввод данных осуществляется из различных строк. Все вышесказанное в равной мере относится к операциям записи с помощью процедур Write и Writeln.

При организации операций ввода-вывода используются специальные языковые средства в виде функций Eoln, Eof, SeekEoln, SeekEof.

Функция Eoln(var F: text) возвращает булевское значение True, если текущая файловая позиция находится на маркере конца строки или вызов Eof(F) вернул значение True. Во всех остальных случаях значение функции будет False.

Функция Eof(var F: text) возвращает булевское значение True, если указатель конца файла находится сразу за последним компонентом, и False – в противном случае.

Функция SeekEoln(var F: text) возвращает булевское значение True при достижении маркера конца строки, причем указатель файла пропускает все пробелы и знаки табуляции, предшествующие маркеру. В противном случае функция возвращает значение False.

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

Пример

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

Этапы решения задачи:

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

2. Составим блок -схему программы.

 

Содержимое самих блоков не должно вызвать больших затруднений в смысловом понимании, главное здесь это - техническая реализации на языке Паскаль, поэтому запишем реализации каждого блока на Паскале.

а) "Считываем строки из файла F" assign(f,'input.dat'); reset(f); while not eof(f) do begin readln(f,st); end; б) "Переворачиваем строки и записываем их в массив" st1:=''; for i:= 1 to length(st) do st1:= st[i]+st1; m[k]:=st1; k:=k+1; в) "Записываем в файл g" assign(g,'output.dat'); rewrite(g); for i:= 1 to k do writeln(g,m[i]); 3. Программа целиком program example; var f,g:text; m:array[1..100] of string; k,i:integer; st,st1:string; begin assign(f,'input.dat'); reset(f); k:=0; while not eof(f) do begin readln(f,st); k:=k+1; st1:=''; for i:= 1 to length(st) do st1:= st[i]+st1; m[k]:=st1; end; assign(g,'output.dat'); rewrite(g); for i:= 1 to k do writeln(g,m[i]); end.

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

var FileVar: file of тип;

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

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

Для определения количества записей в файле можно использовать функцию FileSize, которая возвращает именно количество записей, а не длину файла, как это следует из ее названия.

Для определения текущей позиции в файле можно использовать функцию FilePos.

Для уменьшения длины файла можно использовать процедуру Truncate, которая обрезает файл по текущей позиции

Замечания по поводу открытия файлов, для этого используются две ранее описанные процедуры: ReWrite - создает новый файл для чтения/записи, если такой файл существует, то его длина устанавливается в ноль и Reset - открывает файл для чтения/записи и не изменяет его длины. Сразу видно различие в этих процедурах по отношению к текстовым файлам.

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

Type TPhoneRec = packed record PersonName: string[25]; Address: string[25]; Phone: string[16]; end;

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

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

Var PersonFile: file of TPhoneRec; // определили файл нашего типа DbOpen: Boolean; // флаг состояния базы PhonesCount: Integer // количество записей в базе   // открытие базы и инициализация // не пытаться работать с базой если результат = FALSE function OpenDB(const DBName: string): Boolean; begin AssignFile(PersonFile, DBName); try Reset(PersonFile); // открываем базу PhonesCount := FileSize(PersonFile); // текущее количество записей DbOpen := TRUE; // открытие прошло нормально except PhonesCount := 0; DbOpen := FALSE; end; Result := DbOpen; end;   // создание новой базы и инициализация // не пытаться работать с базой если результат = FALSE function CreateDB(const DBName: string): Boolean; begin AssignFile(PersonFile, DBName); try Rewrite(PersonFile);// открываем базу DbOpen := TRUE; // открытие прошло нормально except DbOpen := FALSE; end; PhonesCount := 0; // записей нет Result := DbOpen; end;   // закрытие базы function CloseDB: Boolean; begin if DbOpen then CloseFile(PersonFile); end;   // Удвлить все после указанной записи function TruncateDB(const RecNo: Integer); begin Seek(PersonFile, RecNo); Truncate(PersonFile); end;   // Читать следующую, за указателем запись function ReadNextRec: TPersonRec; begin Read(PersonFile, Result); end;   // Читать указанную запись function ReadRec(const RecNo: Integer): TPersonRec; begin Seek(PersonFile, RecNo); Result := ReadNextRec; end;   // изменить следующую, за указателем запись procedure ModifyNextRec(const RecNo: Integer; const Rec: TPersonRec); begin Write(PersonFile, Rec); end;   // изменить указанную запись procedure ModifyRec(const RecNo: Integer: const Rec: TPersonRec); begin Seek(PersonFile, RecNo); ModifyNextRec(Rec); end;   // Добавить новую запись в конец файла procedure AddRec(const Rec: TPersonRec); begin Seek(PersonFile, PhonesCount); // переместиться на последнею запись ModifyNextRec(Rec); // и добавить запись PhonesCount := FileSize(PersonFile); // новое количество записей end;

Контрольные вопросы

1. Что такое файл? Какие существуют виды файлов?

2. Какими стандартными процедурами и функциями располагает Borland Pascal для работы с файлами?

3. Каково должно быть содержание программы по созданию файла и его корректировки (замена элементов, добавление элементов, удаление элементов)?

4. Каковы особенности работы с текстовыми файлами?

5. Каковы особенности работы с типизированными файлами?

6. Как подсчитать число строк в текстовом файле?

Задания

 

Работа с текстовыми файлами:

1. С помощью текстового редактора создать файл, содержащий текст, длина которого не превышает 1000 символов (длина строки текста не должна превышать 70 символов). Имя файла должно иметь расширение DAT. Написать программу, которая:

· выводит текст на экран дисплея;

· по нажатию произвольной клавиши поочередно выделяет каждое предложение текста;

· определяет количество предложений в тексте.

2. С помощью текстового редактора создать файл, содержащий текст, длина которого не превышает 1000 символов (длина строки текста не должна превышать 70 символов). Имя файла должно иметь расширение DAT. Написать программу, которая:

· выводит текст на экран дисплея;

· по нажатию произвольной клавиши поочередно выделяет каждое слово текста;

· определяет количество слов в тексте.

3. С помощью текстового редактора создать файл, содержащий текст, длина которого не превышает 1000 символов (длина строки текста не должна превышать 70 символов). Имя файла должно иметь расширение DAT. Написать программу, которая:

· выводит текст на экран дисплея;

· по нажатию произвольной клавиши поочередно выделяет каждое слово текста, оканчивающееся на гласную букву;

· определяет количество слов в тексте, оканчивающихся на гласную букву.

4. С помощью текстового редактора создать файл, содержащий текст, длина которого не превышает 1000 символов (длина строки текста не должна превышать 70 символов). Имя файла должно иметь расширение DAT. Написать программу, которая:

· выводит текст на экран дисплея;

· по нажатию произвольной клавиши поочередно выделяет предложения текста в последовательности 2, 1, 3, 5, 4, 6.

5. С помощью текстового редактора создать файл, содержащий текст, длина которого не превышает 1000 символов (длина строки текста не должна превышать 70 символов). Имя файла должно иметь расширение DAT. Написать программу, которая:

· выводит текст на экран дисплея;

· по нажатию произвольной клавиши выделяет поочередно те слова текста, у которых совпадают первый и последний символы;

· определяет количество таких слов в тексте.

6. С помощью текстового редактора создать файл, содержащий текст, длина которого не превышает 1000 символов (длина строки текста не должна превышать 70 символов). Имя файла должно иметь расширение DAT. Написать программу, которая:

· выводит текст на экран дисплея;

· по нажатию произвольной клавиши поочередно выделяет каждое слово текста, начинающееся на гласную букву;

· определяет количество таких слов в тексте.

7. С помощью текстового редактора создать файл, содержащий текст, длина которого не превышает 1000 символов (длина строки текста не должна превышать 70 символов). Имя файла должно иметь расширение DAT. Написать программу, которая:

· выводит текст на экран дисплея;

· определяет количество символов в самом длинном слове;

· по нажатию произвольной клавиши поочередно выделяет слова, содержащие максимальное количество символов.

8. С помощью текстового редактора создать файл, содержащий текст, длина которого не превышает 1000 символов (длина строки текста не должна превышать 70 символов). Имя файла должно иметь расширение DAT. Написать программу, которая:

· выводит текст на экран дисплея;

· определяет количество символов в самом коротком слове;

· по нажатию произвольной клавиши поочередно выделяет слова, содержащие минимальное количество символов.

9. С помощью текстового редактора создать файл, содержащий текст, длина которого не превышает 1000 символов (длина строки текста не должна превышать 70 символов). Имя файла должно иметь расширение DAT. Написать программу, которая:

· выводит текст на экран дисплея;

· определяет в каждом предложении количество символов, отличных от букв и пробелов;

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

10. С помощью текстового редактора создать файл, содержащий текст, длина которого не превышает 1000 символов (длина строки текста не должна превышать 70 символов). Имя файла должно иметь расширение DAT. Написать программу, которая:

· выводит текст на экран дисплея;

· определяет количество предложений в тексте и количество слов в каждом предложении;

· по нажатию произвольной клавиши поочередно выделяет каждое предложение, а в выделенном предложении - поочередно все слова.

 

Работа с типизированными файлами:

 

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

a) Найти багаж, средний вес одной вещи в котором отличается не более, чем на 0.3 кг от общего среднего веса одной вещи.

b) Найти число пассажиров, имеющих более двух вещей и число пассажиров, количество вещей которых превосходит среднее число вещей.

c) Определить, имеются ли два пассажира, багажи которых совпадают по числу вещей и различаются по весу не более чем на 0,5 кг.

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

e) Выяснить, имеется ли пассажир, багаж которого состоит из одной вещи весом менее 30 кг.

2. Прямая на плоскости задается уравнением ax+by+c=0, где a и b одновременно не равны нулю. Будем рассматривать только прямые, для которых коэффициенты a,b,c - целые числа. Пусть f - файл, содержащий коэффициенты нескольких прямых (не менее трех). Переписать из файла f в файл g коэффициенты тех прямых, которые:

a) параллельны первой из прямых, заданной в файле f;

b) указаны в пункте а), но дополнительно требуется, чтобы все прямые были различны;

c) пересекают первую из прямых, заданных в файле f;

d) указаны в пункте b), но дополнительно требуется, чтобы среди прямых не было параллельных.

3. Условие предыдущей задачи сохраняется. Требуется получить в файле g коэффициенты всех различных прямых файла f.

4. Сведения об ученике состоят из его имени и фамилии и названия класса (года обучения и буквы), в котором он учится. Дан файл f, содержащий сведения об учениках школы:

a) выяснить, имеются ли в школе однофамильцы;

b) выяснить, имеются ли однофамильцы в каких-либо параллельных классах;

c) выяснить, имеются ли однофамильцы в каком-нибудь классе;

d) ответить на вопросы а)-в), но в отношении учеников, у которых совпадают и имя, и фамилия;

e) выяснить, в каких классах насчитывается более 35 учащихся;

f) выяснить на сколько человек в восьмых классах больше, чем в десятых;

g) собрать в файле g сведения об учениках 9-х и 10-х классов, поместив вначале сведения об учениках класса 9а, затем 9б и т.д., затем 10а, 10б и т.д.

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

a) выяснить, сколько учеников школы не имеют отметок ниже четырех;

b) собрать в файле g сведения о лучших учениках школы, т.е. об учениках, не имеющих отметок ниже четырех и по сумме баллов не уступающих другим ученикам своего и параллельных классов.

6. Сведения об автомобиле состоят из его марки, номера и фамилии владельца. Дан файл f, содержащий сведения о нескольких автомобилях. Найти: а) фамилии владельцев и номера автомобилей данной марки; б) количество автомобилей каждой марки. Найденные данные записать в файл g.

7. Дан файл f, содержащий различные даты. Каждая дата - это число, месяц и год. Найти: а) год с наименьшим номером; б) все весенние даты; в) самую позднюю дату. Найденные данные записать в файл g.

8. Дан файл f, содержащий сведения о книгах. Сведения о каждой из книг - это фамилия автора, название и год издания. 1) Найти названия книг данного автора, изданных с 1960 г. 2) Определить, имеется ли книга с названием "Информатика". Если да, то сообщить фамилию автора и год издания. Если таких книг несколько, то сообщить имеющиеся сведения обо всех книгах.

9. Дан файл f, содержащий сведения о кубиках: размер каждого кубика (длина ребра в сантиметрах), его цвет (красный, зеленый, желтый или синий) и материал (деревянный, металлический, картонный). Найти: а) количество кубиков каждого из перечисленных цветов и их суммарный объем; б) количество деревянных кубиков с ребром 3 см и количество металлических кубиков с ребром, большим 5 см.

10. Дан файл f, содержащий сведения о веществах: указывается название вещества, его удельный вес и проводимость (проводник, полупроводник, изолятор). 1) Найти удельные веса и названия всех полупроводников. 2) Выбрать данные о проводниках и упорядочить их по убыванию удельных весов.


 

Приложение