2012-01-09 38 views
0

免责声明:不要使用::feof()作为你的循环条件。例如,看到答案:file reading: feof() for binary files为什么:: feof()与:: _ eof(:: fileno())不同?

不过,我有“真实”的代码,演示了不使用::feof()作为我的循环条件的问题,但在逻辑上,这是为了说明问题的最简单的方法。

考虑以下情况:我们遍历一个字符流一在-A-时间:

FILE* my_file; 
// ...open "my_file" for reading... 

int c; 
while(0 == ::feof(my_file)) 
{ // We are not at EOF 
    c = ::getc(my_file); 
    // ...process "c" 
} 

上面的代码按预期工作:文件处理单字符-AT-A-时间,并在EOF,我们退出。

然而,下面有意外的行为

FILE* my_file; 
// ...open "my_file" for reading... 

int c; 
while(0 == ::_eof(::fileno(my_file))) 
{ // We are not at EOF 
    c = ::getc(my_file); 
    // ...process "c" 
} 

我本来期望他们执行相同。 ::fileno()每次都正确地返回(整数)文件描述符。然而,测试::_eof(::fileno(my_file))工作恰好一次,然后在第二次尝试返回1(指示EOF)。

我不明白这一点。

我想可以设想::feof()是“缓冲”(所以它工作正常),而::_eof()是“未缓冲”,并认为整个文件已被“读入”(因为整个文件将适合从磁盘读入的第一个块)。但是,鉴于这些功能的目的,这不可能是真实的。所以,我真的很茫然。

发生了什么事?

(文件被打开的 “文字”,是ASCII文本文件与大约十几行,MSVS2008中,Win7/64)。

+1

您应该检查getc()的返回值以检查EOF。 if(c!= EOF)http://www.cplusplus.com/reference/clibrary/cstdio/getc/ – 2012-01-09 03:13:35

+0

您的代码仍然不正确。您必须在*阅读后检查EOF *,但在*处理之前检查。直到遇到它,才会看到文件结尾。 – 2012-01-09 03:14:06

+0

同意上面的两条评论(@Rajendran && @Kerrek)。但是,这些问题在我的用例中不存在:文件不是空的,并且有多行; 'feof()'正常工作; '_eof(fileno())'在第一个字符被读取后失败(返回'1')。所以,关于我的“不正确的情况”的合理投诉不适用于这种情况。 (这就是为什么我带着一个免责声明来领导。) – charley 2012-01-09 03:26:42

回答

5

我想这是可以想象:: FEOF()的“缓冲“(所以它正常工作 ),而:: _ eof()是”未缓冲“,并且认为整个文件 已经是”已读入“(因为整个文件将适合从磁盘读入的第一个块 )。但是,考虑到这些功能的目的,这不可能是真实的 。所以,我真的很茫然。

我不知道为什么你会认为它“考虑到这些功能的目的不可能是真的”。这两个功能是为了操作打开并以不同方式操作的文件,因此它们不兼容。

事实上,这正是发生的情况。试试这个:

FILE* my_file; 
// ...open "my_file" for reading... 

int c; 
while(0 == ::_eof(::fileno(my_file))) 
{ // We are not at EOF 
    c = ::getc(my_file); 

    long offset1 = ftell(my_file); 
    long offset2 = _tell(fileno(my_file)); 

    if (offset1 != offset2) 
    { 
    //here you will see that the file pointers are different 
    //which means that _eof and feof will fire true under different conditions 
    } 
    // ...process "c" 
} 

我会尽量根据您的意见详细阐述一下。

当您打电话给fopen时,您将回到一个指向文件的指针。基础流对象保留它自己的文件指针,它与基本文件描述符关联的文件指针独立于实际的。

当您调用_eof时,您在询问您是否已达到实际文件的末尾。当你打电话给feof时,你问你是否已经到达文件末尾。由于文件流通常被缓冲,文件的末尾在流结束之前到达。

我还是想知道,下面你的答案,什么目的 是_EOF(),如果它总是返回1,即使你没看过 什么(第一个字符后)。

要回答这个问题,_EOF的目的是为了确定您是否使用_open和_read直接与文件描述符工作的时候到达了文件的末尾,而不是当您使用的fopen和FREAD或GETC工作与文件流。

+0

我花了一些时间来总结/理解@杰拉德在他的回答中是正确的。谢谢,@杰拉德! – charley 2013-04-20 14:54:11

相关问题