Давно уже не работал с CRT и, недавно, обнаружил неприятный сюрприз: функция feof() возвращает true только после того как был прочитан байт следующий за последним. То есть, если есть файл нулевой длинны, то первый вызов feof() вернёт false, а true будет возвращено только после первой попытки чтения. В результате следующая запись не верна:
Во-первых любопытно, почему feof() так странно себя ведёт, есть этому какое-то логическое обоснование? Во-вторых как написать правильную функцию feof() через другие функции CRT? Функции f_length() нет или я её не нашёл?
Здравствуйте, WinterMute, Вы писали:
WM>Во-первых любопытно, почему feof() так странно себя ведёт, есть этому какое-то логическое обоснование? Во-вторых как написать правильную функцию feof() через другие функции CRT? Функции f_length() нет или я её не нашёл?
Я ноль в CRT-вском I/O, но поиск по группам показал, что, вроде бы, feof считается малолезной и редкоиспользуемой функцией и рекомендуется проверять на EOF
Здравствуйте, shank, Вы писали:
S>Здравствуйте, WinterMute, Вы писали:
WM>>Во-первых любопытно, почему feof() так странно себя ведёт, есть этому какое-то логическое обоснование? Во-вторых как написать правильную функцию feof() через другие функции CRT? Функции f_length() нет или я её не нашёл?
S>Я ноль в CRT-вском I/O, но поиск по группам показал, что, вроде бы, feof считается малолезной и редкоиспользуемой функцией и рекомендуется проверять на EOF S>
Здравствуйте, shank, Вы писали:
S>Здравствуйте, WinterMute, Вы писали:
WM>>>EOF валидное значение в бинарном файле, в общем случае это плохой способ.
WM>>Ну и, в Win 1251 EOF == 'я'
S>EOF это целое число равное -1, т.е. 0xFFFFFFFF. Символы, возвращаемые getc, могут быть в диапазоне от 0 до 0xFF. S>Или я чего-то не понимаю?
Наверное ты прав, я обрезал значение до ширины байта. Но вопрос с eof() тем не менее всё ещё интересует.
Здравствуйте, WinterMute, Вы писали:
WM>>Наверное ты прав, я обрезал значение до ширины байта. Но вопрос с eof() тем не менее всё ещё интересует.
WM>Дело в том, что у меня есть интерфейс с двумя методами:
WM>bool has_data() WM>char pop_char()
WM>и мне нужно попроще обернуть в них вызовы CRT.
так может ?
bool has_data()
{
long pos = ftell( m_file );
fseek( m_file, 0, SEEK_END ); // эти 3 строчки можно делать и в конструкторе long size = ftell( m_file ); // получим размер файла
fseek( m_file, pos, SEEK_SET ); // восстановимreturn( pos < size );
}
char pop_char() { /**/ }
оптимизации можно прикрутить на свой вкус, я просто идею хотел показать.
WinterMute wrote:
> Дело в том, что у меня есть интерфейс с двумя методами: > > bool has_data() > char pop_char() > > и мне нужно попроще обернуть в них вызовы CRT.
Запоминай прочитанный символ. Что-то вроде:
class Reader
{
int c;
Reader()
{
c = fgetc(...);
}
char pop_char()
{
assert(has_data());
char result = c;
c = fgetc();
return result;
}
bool has_data()
{
return c != EOF;
}
};
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, WinterMute, Вы писали:
WM>Давно уже не работал с CRT и, недавно, обнаружил неприятный сюрприз: функция feof() возвращает true только после того как был прочитан байт следующий за последним.
Не совсем. После того, как была предпринята попытка чтения данных и эта попытка провалилась именно из-за достижения конца файла.
>То есть, если есть файл нулевой длинны, то первый вызов feof() вернёт false, а true будет возвращено только после первой попытки чтения. В результате следующая запись не верна:
WM>
while((c = (char)getc()) != -1)
printf("%c");
// А теперь можем проверить feof и/или ferror - почему мы вышли из цикла (ошибка или EOF).
WM>Во-первых любопытно, почему feof() так странно себя ведёт, есть этому какое-то логическое обоснование? Во-вторых как написать правильную функцию feof() через другие функции CRT? Функции f_length() нет или я её не нашёл?
Смотрите:
The function feof() tests the end-of-file indicator for the stream pointed to by stream
А уто устанавливает "the end-of-file indicator" ? Очевидно, что кто-то из read-функций, и только _после_ попытки чтения за пределами файла.
Почему не делается проверка, скажем, после каждого успешного чтения? Потому что в общем случае p_f у Вас — это совсем даже не обязательно регулярный файл, и совершив успешное чтение и достигнув после этого конца потока, мы ьем не менее пока не можем установить флаг конца файла, т.к. вполне вероятна ситуация, что данные в потоке появятся даже ранее, чем мы успеем этим feof воспользоваться.
Считайте feof() частным случаем ferror().
Здравствуйте, Vladimir D Belousov, Вы писали:
VDB>Чуть выше было вполне хорошее решение:
VDB>
VDB>while((c = (char)getc()) != -1)
VDB> printf("%c");
VDB>// А теперь можем проверить feof и/или ferror - почему мы вышли из цикла (ошибка или EOF).
VDB>
Как выяснилось выше, для правильной работы программы, переменная c должна иметь тип int и соответственно приведение возвращаемого значения getc к char тоже надо убрать.
Здравствуйте, shank, Вы писали:
S>Здравствуйте, Vladimir D Belousov, Вы писали:
VDB>>Чуть выше было вполне хорошее решение:
VDB>>
VDB>>while((c = (char)getc()) != -1)
VDB>> printf("%c");
VDB>>// А теперь можем проверить feof и/или ferror - почему мы вышли из цикла (ошибка или EOF).
VDB>>
S>Как выяснилось выше, для правильной работы программы, переменная c должна иметь тип int и соответственно приведение возвращаемого значения getc к char тоже надо убрать.
К слову, точно.
Хотя один фиг:
RETURN VALUES
If successful, these routines return the next requested object from the
stream. Character values are returned as an unsigned char converted to
an int.
Vladimir D Belousov wrote: > VDB>>while((c = *(char)*getc()) != -1) > К слову, точно. > Хотя один фиг:
Сказали же, для проверки на EOF (-1) обязательно сравнивать как int. Иначе на буквах "я" в cp1251 будет прекращать чтение.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, kan_izh, Вы писали:
_>Vladimir D Belousov wrote: >> VDB>>while((c = *(char)*getc()) != -1) >> К слову, точно. >> Хотя один фиг: _>Сказали же, для проверки на EOF (-1) обязательно сравнивать как int. Иначе на буквах "я" в cp1251 будет прекращать чтение.