Управление указателем файла

Чтение и запись выполняются в том месте файла, где находится указатель файла. Установить указатель можно функцией

 

int fseek(FILE *stream, long offset, int whence)

 

offset - смещение указателя;

whence – способ отсчета смещения (в переводе whence означает «откуда» ).

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

 

Для указания точки отсчета смещения используют константы:

SEEK_SET — отсчет от начала файла;

SEEK_CUR — отсчет от текущей позиции указателя.

SEEK_END — отсчет от конца файла;

 

Функция

 

long ftell(FILE *stream)

возвращает текущую позицию указателя. При ошибке возвращает -1 и устанавливает глобальную переменную errno в ненулевое значение.

Замечание. Те же действия выполняются функциями fsetpos и fgetpos.

 

Пример. Определить длину файла xxx.bin.

ß

FILE *in = fopen("c:\\xxx.bin","rb");

if (!in) return;

 

fseek(in, 0, SEEK_END); // ставим указатель в конец файла

cout << ftell(in); // определяем позицию указателя

Состояние потока

Макрос, проверяющий достижение конца файла потока:

 

int feof (FILE *stream)

 

возвращает не 0, если достигнут конец файла, и 0 — в противном случае.

 

Макрос, тестирующий индикатор ошибки потока:

 

int ferror(FILE *stream)

возвращает не 0, если обнаружена ошибка записи или чтения.

 

Однажды установленный индикатор ошибки сохраняется до выполнения функций clearerr, rewind или закрытия потока. Индикатор “конец файла” переустанавливается каждой операцией чтения.

 

Макрос, обнуляющий индикаторы ошибки и конца файла.

 

void clearerr(FILE *stream)

 

Макрос

void rewind(FILE *stream)

делает то же, что clearerr, а также устанавливает указатель в начало файла.

 

При возникновении ошибки глобальная переменная errno (определена в файлах errno.h, stddef.h, stdlib.h) получает ненулевой номер ошибки.

Форматированный вывод

Рассмотренные выше функции выводят информацию в поток без или почти без преобразования. Функция

 

int fprintf(FILE *stream, const char *format [, argument, ...])

 

преобразует выводимые данные [, argument, ...]в последовательность символов, руководствуясь строкой формата format. При успехе функция возвращает количество выведенных в поток байт, при неудаче — константу EOF. Квадратные скобки говорят о необязательности аргумента

 

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

Общий вид спецификации формата следующий:

 

%[флаги][ширина][.точность][размер]тип

§ флаги — признаки выравнивания, использования знаков, десятичной точки, конечных нулей, 8-ичных и 16-ичных префиксов;

§ ширина — минимальное число печатаемых символов с учетом пробелов и нулей;

§ точность — максимальное число печатаемых символов (для целых — минимальное число цифр);

§ размер — определяет размер аргумента;

§ тип — символ спецификации типа — обязательный элемент формата.

 

Пример. Вывести в текстовый файл таблицу умножения на 5.

ß

FILE *out = fopen("c:\\xxx.txt","wt");

for (int i = 2; i < 10; i++)

fprintf(out, "%1d x 5 = %2d\n", i, i * 5);

fclose(out);

Форматированный ввод

Для форматированного ввода из потока применяют функцию

 

int fscanf(FILE *stream, const char *format [, address, ...])

 

Функция возвращает число полей ввода отформатированных и размещенных в памяти. При неудаче функция возвращает EOF.

Функция fscanf рассматривает входной поток как последовательность полей ввода. Поле ввода заканчивается:

§ первым символом пробела (но не включает его);

§ первым символом, который не может быть преобразован по спецификации формата, сопоставленной этому полю;

§ (n+1)-м символом, если спецификация включает ширину поля в n символов.

Функция просматривает последовательность полей ввода, форматирует их и размещает по адресам — аргументам fscanf. Число адресов, спецификаций формата и полей ввода должно быть согласовано.

Строка формата состоит из неотображаемых символов (' ',\t,\n), отображаемых символов (все прочие, кроме '%') и спецификаторов формата. Если fscanf встречает неотображаемый символ в форматной строке, она будет считывать, но не сохранять все неотображаемые символы входного потока вплоть до первого отображаемого символа. Если fscanf встречает отображаемый символ в форматной строке, она прочитает, но не сохранит соответствующий символ входного потока.

Спецификация формата предписывает fscanf чтение, преобразование и размещение в памяти одного входного поля.

Общий вид спецификации формата:

 

%[*][ширина][размер][модиф.типа арг.]тип

* — отменяет присваивание поля ввода;

ширина — максимальное число считываемых символов;

размер — N — near, F — far;

модификатор типа аргумента — изменяет тип адресного аргумента;

тип — символ спецификации типа, обязательный элемент формата.