546 глава 13 быть положительным (переместиться вперед), отрицательным (переместиться назад) или нулевым (остаться на месте).
Третий аргумент устанавливает режим, идентифицирующий стартовую точку. Начиная со стандарта ANSI, в заголовочном файле stdio.h указаны следующие именованные константы для режимов:

В более старых реализациях такие определения могут отсутствовать и вместо них для указания режимов используются числовые значения OL, 1L и 2L, соответственно. Вспомните, что суффикс L идентифицирует значения тип long. Или же в реализации могут быть предусмотрены константы, определенные в другом заголовочном файле. В случае сомнений обращайтесь к руководству пользователя или онлайновому справочнику.
Ниже приведены примеры вызова функции (fp — указатель файла):
fseek(fp, OL, SEEK_SET); // перейти в начало файла
fseeklfp, 10L, SEEK_SET); // перейти на 10 байтов от начала файла
fseeklfp, 2L, SEEK_CUR); // перейти вперед на 2 байта от текущей позиции
fseeklfp, OL, SEEK_END); // перейти в конец файла
fseeklfp, -10L, SEEK_END); // перейти назад на 10 байтов от конца файла
С такими вызовами связаны возможные ограничения, о которых речь пойдет позже в главе.
Значение, возвращаемое fseek(), равно 0, если все в порядке, и -1, если возникла ошибка вроде попытки выхода за границы файла.
Функция f tell() имеет тип long и возвращает текущую позицию в файле. В стандарте ANSI С она объявлена в stdio.h. Поскольку изначально функция f tell() была реализована в Unix, она указывает позицию в файле, возвращая количество байтов от начала файла, причем первый байт получает номер 0, второй — номер 1 и т.д. В ANSI С такое определение применяется к файлам, открытым в двоичном режиме, но не обязательно к файлам, открытым в текстовом режиме. Это одна из причин использования двоичного режима в листинге 13.5.
Теперь мы можем исследовать базовые элементы программы из листинга 13.5. Прежде всего, оператор
fseeklfp, OL, SEEK_END);
устанавливает позицию со смещением 0 байтов от конца файла. Это означает установку позиции в конец файла. Затем оператор
last = ftell(fp);
присваивает last количество байтов от начала до конца файла.
Далее следует цикл:
for (count = 1L; count <= last; count++)
{
fseeklfp, -count, SEEK_END); /* двигаться в обратном направлении */
ch = getc ( fp);
}
Файловый ввод-вывод 547
На первой итерации происходит позиционирование на первый символ перед концом файла (т.е. на финальный символ в файле). После этого данный символ выводится. На следующей итерации позиция устанавливается на предпоследний символ в файле, который затем выводится. Процесс продолжается до тех пор, пока не будет достигнут и выведен первый символ в файле.
Сравнение двоичного и текстового режимов
Программа в листинге 13.4 спроектирована так, чтобы работать в средах Unix и MS-DOS. В Unix имеется только один файловый формат, поэтому никакие специальные корректировки не нужны. Однако MS-DOS требует дополнительного внимания. Многие редакторы MS-DOS помечают конец текстового файла посредством символа . Когда такой файл открывается в текстовом режиме, в С этот символ распознается как признак конца файла. Тем не менее, когда тот же самый файл открывается в двоичном режиме, является обычным символом в файле, а действительный признак конца файла появляется позже. Он может находиться сразу после или же файл может быть дополнен нулевыми символами, чтобы сделать размер файла кратным, скажем, 256. Нулевые символы в среде MS-DOS не отображаются, поэтому мы предусмотрели код, предотвращающий вывод символа .
О другом отличии мы упоминали ранее: символ новой строки текстового файла в MS-DOS представлен с помощью комбинации \r\n. Программа на С, открывающая тот же самый файл в текстовом режиме, “видит” символы \r\n как просто \n, но в случае применения двоичного режима программа видит оба символа, т.е. \r и \n. По данной причине был включен код для подавления вывода \r. Поскольку текстовый файл в Unix обычно не содержит ни , ни \r, этот дополнительный код не затрагивает большинство текстовых файлов в Unix.
Функция ftell() может работать по-разному в текстовом и двоичном режимах. Форматы текстовых файлов многих систем заметно отличаются от модели Unix, в которых подсчет байтов от начала файла не дает осмысленной величины. В стандарте ANSI С утверждается, что для случая текстового режима ftell() возвращает значение, которое может быть использовано в качестве второго аргумента fseek(). Например, в MS-DOS функция ftell() может возвращать количество, при подсчете которого комбинация \r\n рассматривается как один байт.
Читать дальше