По первому тесту выполнил дважды задания. Результат получается правильный (проверял калькулятором). Пишет, что "Задание не проверено" и предлагает повторить. |
Обработка файлов средствами Free Pascal
7.4 Обработка текстовых файлов в языке Free Pascal
При работе с текстовыми файлами следует учесть следующее:
- Действие процедур reset, rewrite, close, rename, erase и функции eof аналогично их действию при работе с компонентными (типизированными) файлами.
- Процедуры seek, trunсate и функция filepos не работают с текстовыми файлами.
- Можно пользоваться процедурой открытия текстового файла append(f), где f — имя файловой переменной. Эта процедура служит для открытия файла в режиме дозаписи в конец файла. Она применима только к уже физически существующим файлам, открывает и готовит их для добавления информации в конец файла.
- Запись и чтение в текстовый файл осуществляются с помощью процедур write, writeln, read, readln следующей структуры:
read ( f, x1, x2, x3,..., xn );
read ( f, x );
readln ( f, x1, x2, x3,..., xn );
readln ( f, x );
write ( f, x1, x2, x3,..., xn );
write ( f, x );
writeln ( f, x1, x2, x3,..., xn );
writeln ( f, x );
В этих операторах f — файловая переменная. В операторах чтения (read, readln) x, x1, x2, x3,..., xn — переменные, в которые происходит чтение из файла. В операторах записи write, writeln x, x1, x2, x3,..., xn — переменные или константы, информация из которых записывается в файл.
Есть ряд особенностей при работе операторов write, writeln, read, readln с текстовыми файлами. Имена переменных могут быть целого, вещественного, символьного и строкового типа. Перед записью данных в текстовый файл с помощью процедуры write происходит их преобразование в тип string. Действие оператора writeln отличается тем, что после указанных переменных и констант в файл записывается символ "конец строки".
При чтении данных из текстового файла с помощью процедур read, readln происходит преобразование из строкового типа к нужному типу данных. Если преобразование невозможно, то генерируется код ошибки, значение которого можно узнать, обратившись к функции IOResult. Компилятор Free Pascal позволяет генерировать код программы в двух режимах: с проверкой корректности ввода-вывода и без неё.
В программу может быть включен ключ режима компиляции. Кроме того, предусмотрен перевод контроля ошибок ввода-вывода из одного состояния в другое:
- {$I+} — режим проверки ошибок ввода-вывода включён;
- {$I-} — режим проверки ошибок ввода-вывода отключён.
По умолчанию, как правило, действует режим {$I+}. Можно многократно включать и выключать режимы, создавая области с контролем ввода и без него. Все ключи компиляции описаны в приложении.
При включённом режиме проверки любая ошибка ввода-вывода будет фатальной, программа прервётся, выдав номер ошибки.
Если убрать режим проверки, то при возникновении ошибки ввода-вывода программа не будет останавливаться, а продолжит работу со следующего оператора. Результат операции ввода-вывода будет неопределён.
Для опроса кода ошибки лучше пользоваться специальной функцией IOResult, но необходимо помнить, что опросить её можно только один раз после каждой операции ввода или вывода: она обнуляет своё значение при каждом вызове. IOResult возвращает целое число, соответствующее коду последней ошибки ввода-вывода. Если IOResult=0, то при вводе-выводе ошибок не было, иначе IOResult возвращает код ошибки. Некоторые коды ошибок приведены в табл. 7.9.
Код ошибки | Описание |
---|---|
2 | файл не найден |
3 | путь не найден |
4 | слишком много открытых файлов |
5 | отказано в доступе |
12 | неверный режим доступа |
15 | неправильный номер диска |
16 | нельзя удалять текущую директорию |
100 | ошибка при чтении с диска |
101 | ошибка при записи на диск |
102 | не применена процедура AssignFile |
103 | файл не открыт |
104 | файл не открыт для ввода |
105 | файл не открыт для вывода |
106 | неверный номер |
150 | диск защищён от записи |
Рассмотрим несколько практических примеров обработки ошибок ввода-вывода:
- При открытии проверить, существует ли заданный файл и возможно ли чтение данных из него.
assign ( f, ’ abc. dat ’ ); {$I-} reset ( f ); {$I+} if IOResult<>0 then writeln ( ’файл не найден или не читается ’ ) else begin read ( f,... ); close ( f ); end;
- Проверить, является ли вводимое с клавиатуры число целым.
var i : integer; begin {$I-} repeat write ( ’введите целое число i ’ ); readln ( i ); until ( IOResult =0); {$I+} {Этот цикл повторяется до тех пор, пока не будет введено целое число.} end.
При работе с текстовым файлом необходимо помнить специальные правила чтения значений переменных:
- Когда вводятся числовые значения, два числа считаются разделёнными, если между ними есть хотя бы один пробел, или символ табуляции, или символ конца строки.
- При вводе строк начало текущей строки идёт сразу за последним, введённым до этого символом. Вводится количество символов, равное объявленной длине строки. Если при чтении встретился символ "конец строки", то работа с этой строкой заканчивается. Сам символ конца строки является разделителем и в переменную никогда не считывается.
- Процедура readln считывает значения текущей строки файла, курсор переводится в новую строку файла, и дальнейший ввод осуществляется с неё.
В качестве примера работы с текстовыми файлами рассмотрим следующую задачу.
Сначала создадим текстовый файл abc.txt следующей структуры: в первой строке через пробел хранятся размеры матрицы (числа N и M), затем построчно хранятся матрицы A и B.
На рис. 7.14 приведён пример файла abc.txt, в котором хранятся матрицы A(4,5) и B(4,5).
Текст консольного приложения решения задачи 7.8 с комментариями приведён ниже.
program Project1; {$mode objfpc}{$H+} uses Classes, SysUtils { you can add units after this }; var f : Text; i, j, N,M: word; a, b, c : array [ 1.. 1000, 1.. 1000 ] of real; begin //Связываем файловую переменную f с файлом на диске. AssignFile ( f, ’ abc. t x t ’ ); //Открываем файл в режиме чтения. Reset ( f ); //Считываем из первой строки файла abc.txt значения N и M. Read( f,N,M); //Последовательно считываем элементы матрицы А из файла. for i :=1 to N do for j :=1 to M do read ( f, a [ i, j ] ); //Последовательно считываем элементы матрицы B из файла. for i :=1 to N do for j :=1 to M do read ( f, b [ i, j ] ); //Формируем матрицу C=A+B. for i :=1 to N do for j :=1 to M do c [ i, j ] : = a [ i, j ]+b [ i ] [ j ]; //Закрываем файл f. CloseFile ( f ); //Открываем файл в режиме дозаписи. Append( f ); //Дозапись матрицы C в файл. for i :=1 to N do begin for j :=1 to M do //Дописываем в файл очередной элемент матрицы и пробел в //текстовый файл. write ( f, c [ i, j ] : 1 : 2, ’ ’ ); //По окончании вывода строки матрицы переходим на новую //строку в текстовом файле. writeln ( f ); end; //Закрываем файл. CloseFile ( f ); end.
После работы программы файл abc.txt будет примерно таким, как показано на рис. 7.15.