Вопрос

Использует fseek вернуть персонажа назад fscanf операции надежны?

Например, если я только что fscanf-ed 10 символов, но я хотел бы вернуться к 10 символам, могу ли я просто fseek(infile, -10, SEEK_CUR) ?

В большинстве ситуаций это работает, но у меня, похоже, проблемы с персонажем. ^M.Видимо fseek регистрирует его как символ, но fscanf не регистрирует его, поэтому в моем предыдущем примере блок из 10 символов содержит ^M потребует fseek(infile, -11, SEEK_CUR) вместо. fseek(infile, -10, SEEK_CUR) сократит его на 1 символ.

Почему это так?

Редактировать:я использовал fopen в текстовом режиме

Это было полезно?

Решение

Вы видите разницу между «текстовым» и «двоичным» файлом.Когда файл открывается в текстовом режиме (во втором аргументе fopen нет буквы «b»), библиотека stdio может (действительно должна) интерпретировать содержимое файла в соответствии с соглашениями операционной системы для текстовых файлов.Например, в Windows строка заканчивается на , и stdio преобразует ее в один , поскольку это соглашение C.При записи в текстовый файл один выводится как .

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

Альтернативно вы можете использовать двоичные файлы и самостоятельно выполнять преобразования конца строк.Опять же, мобильность страдает.

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

Другие советы

Это связано с тем, что fseek работает с байтами, тогда как fscanf разумно обрабатывает возврат каретки и перевод строки на два байта и воспринимает их как один символ.

Fseek не понимает содержимого файла и просто перемещает указатель файла на 10 символов назад.

fscanf в зависимости от ОС может по-разному интерпретировать символы новой строки;возможно даже, что fscanf вставит ^M, если вы работаете в DOS, а ^M не отображается в файле.Проверьте руководство, прилагаемое к компилятору C.

Только что попробовал это с VS2008 и обнаружил, что fscanf и fseek обрабатывают символы CR и LF одинаково (как один символ).

Итак, с двумя файлами:

0000000:3132 3334 3554 3738 3930 3132 3334 3536 12345X7890123456

и

0000000:3132 3334 350d 0a37 3839 3031 3233 3435 12345..789012345

Если я прочитаю 15 символов, я доберусь до вторых «5», затем вернутся к 10 символам, следующим прочитанным символом будет «X» в первом случае и CRLF во втором.

Это похоже на проблему, специфичную для ОС/компилятора.

Вы проверяли возвращаемое значение fscanf?Опубликуйте код.

Взгляни на ungetc.Возможно, вам придется выполнить цикл по нему.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top