странный feof()
От: WinterMute Россия http://yarrr.ru
Дата: 29.08.06 19:01
Оценка:
Давно уже не работал с CRT и, недавно, обнаружил неприятный сюрприз: функция feof() возвращает true только после того как был прочитан байт следующий за последним. То есть, если есть файл нулевой длинны, то первый вызов feof() вернёт false, а true будет возвращено только после первой попытки чтения. В результате следующая запись не верна:

while( !feof(p_f) )
{
    printf( "%c", (char)getc() );
}


Во-первых любопытно, почему feof() так странно себя ведёт, есть этому какое-то логическое обоснование? Во-вторых как написать правильную функцию feof() через другие функции CRT? Функции f_length() нет или я её не нашёл?
Re: странный feof()
От: shank  
Дата: 29.08.06 19:58
Оценка: +1
Здравствуйте, WinterMute, Вы писали:

WM>Во-первых любопытно, почему feof() так странно себя ведёт, есть этому какое-то логическое обоснование? Во-вторых как написать правильную функцию feof() через другие функции CRT? Функции f_length() нет или я её не нашёл?


Я ноль в CRT-вском I/O, но поиск по группам показал, что, вроде бы, feof считается малолезной и редкоиспользуемой функцией и рекомендуется проверять на EOF
while((c = getc(p_f)) != EOF)
{
    printf("%c", c);
}
Re[2]: странный feof()
От: WinterMute Россия http://yarrr.ru
Дата: 29.08.06 20:12
Оценка:
Здравствуйте, shank, Вы писали:

S>Здравствуйте, WinterMute, Вы писали:


WM>>Во-первых любопытно, почему feof() так странно себя ведёт, есть этому какое-то логическое обоснование? Во-вторых как написать правильную функцию feof() через другие функции CRT? Функции f_length() нет или я её не нашёл?


S>Я ноль в CRT-вском I/O, но поиск по группам показал, что, вроде бы, feof считается малолезной и редкоиспользуемой функцией и рекомендуется проверять на EOF

S>
S>while((c = getc(p_f)) != EOF)
S>{
S>    printf("%c", c);
S>}
S>


EOF валидное значение в бинарном файле, в общем случае это плохой способ.
Re[3]: странный feof()
От: WinterMute Россия http://yarrr.ru
Дата: 29.08.06 20:16
Оценка:
WM>EOF валидное значение в бинарном файле, в общем случае это плохой способ.

Ну и, в Win 1251 EOF == 'я'
Re[4]: странный feof()
От: shank  
Дата: 29.08.06 20:27
Оценка: +1
Здравствуйте, WinterMute, Вы писали:

WM>>EOF валидное значение в бинарном файле, в общем случае это плохой способ.


WM>Ну и, в Win 1251 EOF == 'я'


EOF это целое число равное -1, т.е. 0xFFFFFFFF. Символы, возвращаемые getc, могут быть в диапазоне от 0 до 0xFF.
Или я чего-то не понимаю?
Re[5]: странный feof()
От: WinterMute Россия http://yarrr.ru
Дата: 29.08.06 20:38
Оценка:
Здравствуйте, shank, Вы писали:

S>Здравствуйте, WinterMute, Вы писали:


WM>>>EOF валидное значение в бинарном файле, в общем случае это плохой способ.


WM>>Ну и, в Win 1251 EOF == 'я'


S>EOF это целое число равное -1, т.е. 0xFFFFFFFF. Символы, возвращаемые getc, могут быть в диапазоне от 0 до 0xFF.

S>Или я чего-то не понимаю?

Наверное ты прав, я обрезал значение до ширины байта. Но вопрос с eof() тем не менее всё ещё интересует.
Re[6]: странный feof()
От: WinterMute Россия http://yarrr.ru
Дата: 29.08.06 20:44
Оценка:
WM>Наверное ты прав, я обрезал значение до ширины байта. Но вопрос с eof() тем не менее всё ещё интересует.

Дело в том, что у меня есть интерфейс с двумя методами:

bool has_data()
char pop_char()

и мне нужно попроще обернуть в них вызовы CRT.
Re[7]: странный feof()
От: _Dreamer Россия  
Дата: 30.08.06 03:11
Оценка: 4 (1)
Здравствуйте, 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() { /**/ }


оптимизации можно прикрутить на свой вкус, я просто идею хотел показать.
Re[7]: странный feof()
От: kan_izh Великобритания  
Дата: 30.08.06 08:56
Оценка: 2 (2)
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
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re: странный feof()
От: Vladimir D Belousov Россия  
Дата: 30.08.06 13:34
Оценка:
Здравствуйте, WinterMute, Вы писали:

WM>Давно уже не работал с CRT и, недавно, обнаружил неприятный сюрприз: функция feof() возвращает true только после того как был прочитан байт следующий за последним.


Не совсем. После того, как была предпринята попытка чтения данных и эта попытка провалилась именно из-за достижения конца файла.

>То есть, если есть файл нулевой длинны, то первый вызов feof() вернёт false, а true будет возвращено только после первой попытки чтения. В результате следующая запись не верна:


WM>
WM>while( !feof(p_f) )
WM>{
WM>    printf( "%c", (char)getc() );
WM>}
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().
--
Спасибо
Re[2]: странный feof()
От: shank  
Дата: 30.08.06 13:45
Оценка:
Здравствуйте, Vladimir D Belousov, Вы писали:

VDB>Чуть выше было вполне хорошее решение:


VDB>
VDB>while((c = (char)getc()) != -1)
VDB>   printf("%c");
VDB>// А теперь можем проверить feof и/или ferror - почему мы вышли из цикла (ошибка или EOF).
VDB>


Как выяснилось выше, для правильной работы программы, переменная c должна иметь тип int и соответственно приведение возвращаемого значения getc к char тоже надо убрать.
Re[3]: странный feof()
От: Vladimir D Belousov Россия  
Дата: 30.08.06 13:52
Оценка:
Здравствуйте, 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.
--
Спасибо
Re[4]: странный feof()
От: kan_izh Великобритания  
Дата: 30.08.06 14:17
Оценка:
Vladimir D Belousov wrote:
> VDB>>while((c = *(char)*getc()) != -1)
> К слову, точно.
> Хотя один фиг:
Сказали же, для проверки на EOF (-1) обязательно сравнивать как int. Иначе на буквах "я" в cp1251 будет прекращать чтение.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[5]: странный feof()
От: Vladimir D Belousov Россия  
Дата: 30.08.06 15:50
Оценка:
Здравствуйте, kan_izh, Вы писали:

_>Vladimir D Belousov wrote:

>> VDB>>while((c = *(char)*getc()) != -1)
>> К слову, точно.
>> Хотя один фиг:
_>Сказали же, для проверки на EOF (-1) обязательно сравнивать как int. Иначе на буквах "я" в cp1251 будет прекращать чтение.

Ну да, это очевидно — я и не спорю.
--
Спасибо
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.