feof(fp)= =0和!feof(fp)作为判断文件是否结束条件的区别?

C语言 feof() 函数用于检测文件是否结束,既适用于二进制文件,也适用于文本文件。

其中,“文件指针”指向一个已经打开并正在操作的文件。

功能:测试文件指针 fp 所指向的文件是否已读到文件尾部。若已读到文件末尾,返回值为 1;否则,返回值为 0。

说明:在进行读文件操作时,需要检测是否读到文件的结尾处,常用while(!feof(fp))循环语句来控制文件中内容的读取。

如当前读取的内容不是文件尾部,则 feof(fp) 的值为 0,取非运算后值为 1,那么循环继续执行;若已读到文件结尾,则 feof(fp) 的值为 1,取非运算后值为0,循环结束,也即是读文件操作结束。

例如,顺序读取文本文件中的字符,代码如下。


}

while(!feof) 是错误的,因为它测试的是一些不相关的东西,而没有测试你需要知道的东西。其结果是,你错误地执行代码,假设它正在访问已成功读取的数据,而事实上这从未发生过。

我想提供一个抽象的、高层次的观点。所以,如果你对while(!feof) 的实际工作感兴趣,请继续阅读。

I/O操作与环境相互作用。环境不是你程序的一部分,也不在你的控制之下。环境确实与你的程序 "同时 "存在。就像所有的并发性事物一样,关于 "当前状态 "的问题是没有意义的。并发事件之间不存在 "同时性 "的概念。许多状态的属性根本不存在并发性。

让我把这个问题说得更精确些。假设你想问,"你是否有更多的数据"。你可以问一个并发的容器,或者你的I/O系统的这个问题。但这个答案通常是不可操作的,因此是没有意义的。如果容器说 "是的",那又如何呢--当你尝试读取时,它可能已经没有数据了。同样,如果答案是 "不",当你尝试读取时,数据可能已经到达。结论是,根本不存在"我有数据 "这样的属性,因为你无法对任何可能的答案做出有意义的反应。(缓冲输入的情况稍好一些,在那里你可以想象得到 "是的,我有数据",这构成了某种保证,但你仍然必须能够处理相反的情况。而在输出方面,情况肯定和我描述的一样糟糕:你永远不知道那个磁盘或那个网络缓冲区是否已经满了)。

所以我们得出结论,询问一个I/O系统是否能够执行I/O操作是不可能的,事实上也是不合理的。我们与它互动的唯一可能的方式(就像与并发容器一样)是尝试操作,并检查它是否成功或失败。在你与环境交互的那一刻,只有在那时你才能知道交互是否真的可行,而在那时你必须承诺执行交互。(如果你愿意的话,这就是一个 "同步点")。

现在我们来谈谈EOF。EOF是你从一个尝试的I/O操作中得到的响应。它意味着你试图读或写一些东西,但在这样做的时候,你没能读或写任何数据,而是遇到了输入或输出的结束。基本上所有的I/O API都是如此,无论是C标准库、C++ iostreams,还是其他库。只要I/O操作成功,你就无法知道进一步的、未来的操作是否会成功。你必须首先尝试操作,然后对成功或失败做出反应。

在每个例子中,请仔细注意,我们首先尝试I/O操作,然后如果结果是有效的,就消费它。进一步注意,我们总是必须使用I/O操作的结果,尽管在每个例子中结果的形状和形式不同。

  • C stdio,从一个文件中读取。

    我们必须使用的结果是n ,即被读取的元素数(可能少到零)。

  • 我们必须使用的结果是scanf 的返回值,即转换的元素数量。

  • 我们必须使用的结果是std::cin 本身,它可以在布尔上下文中进行评估,并告诉我们流是否仍然处于good() 状态。

  • 我们必须使用的结果还是std::cin ,就像以前一样。

  • 我们在这里使用的结果是k ,即写入的字节数。这里的重点是,我们只能知道在写操作之后写了多少字节。

  • 我们必须使用的结果是nbytes ,即包括换行在内的字节数(如果文件不是以换行结束,则为EOF)。

    注意,当发生错误或达到EOF时,该函数明确地返回-1 (而不是EOF!)。

你可能注意到,我们很少拼出 "EOF "这个实际的词。我们通常以其他一些我们更感兴趣的方式来检测错误情况(例如,未能执行我们所期望的I/O)。在每个例子中,都有一些API功能可以明确地告诉我们遇到了EOF状态,但事实上这并不是一个非常有用的信息。它比我们经常关心的细节要多得多。重要的是I/O是否成功,而不是它如何失败。

  • 最后一个例子是实际查询EOF状态的。假设你有一个字符串,想测试它是否完整地代表了一个整数,除了空白之外,结尾没有多余的位。使用C++的iostreams,它是这样的。

我们在这里使用两个结果。第一个是iss ,即流对象本身,以检查对value 的格式化提取是否成功。但随后,在同样消耗了空白空间之后,我们执行另一个I/O/操作,iss.get() ,并期望它以EOF的形式失败,如果整个字符串已经被格式化提取消耗了,就会出现这种情况。

在C语言标准库中,你可以通过检查结束指针是否已经到达输入字符串的末端,用strto*l 函数实现类似的目的。

}

我要回帖

更多关于 fscanf和scanf区别 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信