如何知道下一个字符是不是是 C++ 中的 EOF
Posted
技术标签:
【中文标题】如何知道下一个字符是不是是 C++ 中的 EOF【英文标题】:How to know if the next character is EOF in C++如何知道下一个字符是否是 C++ 中的 EOF 【发布时间】:2011-06-08 18:43:51 【问题描述】:我需要知道ifstream
中的下一个字符是否是文件的结尾。我正在尝试使用.peek()
:
if (file.peek() == -1)
和
if (file.peek() == file.eof())
但两者都不起作用。有办法做到这一点吗?
编辑: 我要做的是在文件中每个单词的末尾添加一个字母。为了做到这一点,我询问下一个字符是否是标点符号,但是这样最后一个单词就没有多余的字母了。我只使用char
,而不是string
。
【问题讨论】:
你不应该这样做。它不会告诉您下一次读取是否会失败。你想完成什么? 你想要达到的目标是什么,这让你需要知道。也许如果您描述更大的问题,我们可以建议如何解决问题。 如果您真的想针对 EOF 进行测试,请尝试if (file.peek() == ifstream::traits_type::eof())
。但正如 littleadv 指出的那样,peek()
实际上会在流本身上设置 EOF 位。所以正如 rubenvb 指出的那样,你想做什么?
【参考方案1】:
istream::peek()
在检测到文件结尾或错误时返回常量EOF
(不保证等于-1)。要可靠地检查文件结尾,请执行以下操作:
int c = file.peek();
if (c == EOF)
if (file.eof())
// end of file
else
// error
else
// do something with 'c'
您应该知道,底层操作系统原语read(2)
仅在您尝试读取文件末尾过去时发出 EOF 信号。因此,file.eof()
在您仅读取直到文件中的最后一个字符时不会为真。也就是说,file.eof()
为 false 并不意味着下一次读取操作会成功。
【讨论】:
在 100% 洁净的 C++ 中,EOF
是 std::ifstream::traits_type::eof()
。
std::ifstream::traits_type
是 std::char_traits<char>
,std::char_traits<char>::eof()
定义为 EOF
。 C++98 [lib.char.traits.specializations.char]/7。如果您使用的是宽流,则需要使用WEOF
,如果您将basic_ifstream
与您自己的特征类一起使用,您当然会使用该类的eof()
,但我认为没有理由使用不需要时引用特征类型。【参考方案2】:
这应该可行:
if (file.peek(), file.eof())
但是为什么不在尝试读取有用数据后检查错误呢?
【讨论】:
【参考方案3】:file.eof()
返回一个标志值。如果您不能再从文件中读取,则将其设置为 TRUE。 EOF 不是一个实际的字符,它是操作系统的标记。所以当你在那里时 - file.eof()
应该是 true
。
因此,您应该在读取(或窥视)后使用if (true == file.eof())
而不是if (file.peek() == file.eof())
,以检查您是否到达文件末尾(如果我理解正确,这就是您要尝试做的事情)。
【讨论】:
这是错误的,eof-bit 仅设置在 您在文件末尾读取之后。 没有。file.eof()
设置为 true 在尝试读取结束后。它不会告诉你是否刚刚到达终点。
澄清以解决您的 cmets。【参考方案4】:
对于连接到键盘的流,eof 条件是我打算在下一次输入期间键入 Ctrl+D/Ctrl+Z。
peek()
完全看不到这一点。 :-)
【讨论】:
为什么,不是?peek()
会很乐意阻止,直到您做出决定。
@Charles - 是的,如果他一次读取一个字符。一开始他忘了提。【参考方案5】:
通常检查我使用的文件结尾:
if(cin.fail())
// Do whatever here
另一种实现方式是..
while(!cin.fail())
// Do whatever here
其他信息会很有帮助,因此我们知道您想做什么。
【讨论】:
@Neil Butterworth - 这些是我在大学作业中使用的代码的 sn-ps,但介意解释为什么它们是错误的吗? ^^ @tf 你应该检查每个读(和写)操作的结果,当它们发生时,而不是在你做它们之前检查流的状态。 @tf: 检查this question 他们错了,因为read
(最终构建 iostream 的系统调用)仅在您尝试读取 过去结束时发出文件结束信号文件,而不是当您阅读 直到 文件的末尾。您可能在该 while 循环中进行了输入操作,并且您没有费心检查它是否成功,因此我可以制作会破坏您的程序的输入。你的导师应该已经指出了这一点。
@Nail Butterworth,感谢您的启发。 @Xeo,谢谢你指点我这个问题;这很有帮助。【参考方案6】:
没有办法判断下一个字符是否是文件的结尾,尝试这样做是新 C 和 C++ 程序员最常犯的错误之一,因为在文件中没有文件结尾字符大多数操作系统。您可以看出,读取流中的当前位置将读取文件末尾,但这通常是非常无用的信息。相反,您应该测试所有读取操作的成功或失败,并根据该状态采取行动。
【讨论】:
【参考方案7】:您没有显示任何您正在使用的代码,所以我有一些猜测。使用流时,您通常不需要低级设施(如peek()
)。您可能感兴趣的是istream_iterator
。这是一个例子,
cout << "enter value";
for(istream_iterator<double> it(cin), end;
it != end; ++it)
cout << "\nyou entered value " << *it;
cout << "\nTry again ...";
您也可以使用 istreambuf_iterator 直接处理缓冲区:
cout << "Please, enter your name: ";
string name;
for(istreambuf_iterator<char> it(cin.rdbuf()), end;
it != end && *it != '\n'; ++it)
name += *it;
cout << "\nyour name is " << name;
【讨论】:
【参考方案8】:只需在 macOS 中使用此代码
if (true == file.eof())
它在 macosx 中对我有用!
【讨论】:
以上是关于如何知道下一个字符是不是是 C++ 中的 EOF的主要内容,如果未能解决你的问题,请参考以下文章