如何知道下一个字符是不是是 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++ 中,EOFstd::ifstream::traits_type::eof() std::ifstream::traits_typestd::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的主要内容,如果未能解决你的问题,请参考以下文章

C++输入多行数字到数组

如何限制用户仅在 C++ 中输入单个字符

C++怎么用eof判断txt文件到文件结尾了没

如何检查字符串中的数据是不是是 C++ 上的数字?

chars eof啥用

关于文件结束符EOF