Ввод и вывод информации: текстовые файлы
Пробельные символы
К пробельным символам (присутствующим в файле, но невидимым на экране) относятся:
- символ горизонтальной табуляции ( #9 );
- символ перевода строки ( #10 ) (смещение курсора на следующую строку, в той же позиции);
- символ вертикальной табуляции ( #11 );
- символ возврата каретки ( #13 ) (смещение курсора на начальную позицию текущей строки; в кодировке UNIX один этот символ служит признаком конца строки);
- символ конца файла ( #26 );
- символ пробела ( #32 ).
Замечание: Пара символов #13 и #10 является признаком конца строки текстового файла (в кодировках DOS и Windows).
В (текстовом) файле границами чисел служат пробельные символы, и при считывании чисел эти пробельные символы игнорируются, сколько бы их ни было. Таким образом, если ввод многих чисел производится с помощью команды read(), то нет никакой разницы, как именно записаны эти числа: в одну строку, в несколько строк или вовсе в один столбик. В любом случае считывание пройдет корректно и завершится только по достижении конца файла.
Если же считывание тестового файла производится посимвольно, то нужно аккуратно отслеживать пробельные (особенно концевые) символы.
Поиск специальных пробельных символов (нас интересуют в основном #10, #13 и #26 ) можно осуществлять при помощи стандартных функций:
eof(f) - возвращает значение TRUE, если уже достигнут конец файла f (указатель находится сразу за последним элементом файла), и FALSE в противном случае;
seekeof(f) - возвращает значение TRUE, если "почти" достигнут конец файла f (между указателем и концом файла нет никаких символов, кроме пробельных ), и FALSE в противном случае;
eoln(f) - возвращает значение TRUE, если достигнут конец строки в файле f (указатель находится сразу за последним элементом строки), и FALSE в противном случае;
seekeoln(f) - возвращает значение TRUE, если "почти" достигнут конец строки в файле f (между указателем и концом строки нет никаких символов, кроме пробельных ), и FALSE в противном случае.
Ясно, что в большинстве случаев предпочтительнее использовать функции seekeof(f) и seekeoln(f): они предназначены специально для текстовых файлов, игнорируют концы строк (и вообще все пробельные символы ) и потому позволяют автоматически обработать сразу несколько частных случаев.
Например, если по условию задачи файл входных данных может содержать только одну строку, то правильнее всего будет написать программу, обрабатывающую все возможные варианты:
- одна строка, заканчивающаяся символом конца файла;
- одна строка, заканчивающаяся несколькими концевыми пробелами, а затем - символом конца файла;
- одна строка, заканчивающаяся символом конца строки, а затем - символом конца файла (на самом деле получается, что в файле содержится не одна, а две строки, но вторая - пустая);
- одна строка, заканчивающаяся несколькими концевыми пробелами, затем - символом конца строки, а затем - символом конца файла.
Поскольку функции seekeof() и seekeoln() при каждой проверке пытаются проигнорировать все пробельные символы, то и результаты их работы отличаются от результатов работы функций eof() и eoln(). Эти различия нужно учитывать.
Например, для входного файла f, состоящего из двух строк 1_2_ _3_#13#10 (всего 9 символов, вторая строка пустая, подчеркивания здесь обозначают пробелы), следующие куски программ будут выдавать такие результаты:
Cодержимое результирующего файла g |
Длина файла g | |
while not eof(f) do begin read(f,c); {c: char} write(g,c) end; |
1_2_ _3_#13#10 | 9 байт |
while not seekeof(f) do begin read(f,c); {c: char} write(g,c) end; |
123 | 3 байта |
while not eof(f) do while not seekeoln(f) do begin read(f,c); {c: char} write(g,c) end; |
Зацикливание | |
while not seekeof(f) do while not eoln(f) do begin read(f,c); {c: char} write(g,c) end; |
1_2_ _3_ | 7 байт |
while not seekeof(f) do while not eoln(f) do begin read(f,k); {k: byte} write(g,k) end; |
1230 | 4 байта |