【问题标题】:eof() is returning last character twice [duplicate]eof() 两次返回最后一个字符[重复]
【发布时间】:2015-09-18 05:14:38
【问题描述】:

我正在从具有字符串“ABCDEFGH”的输入文件“input.txt”中读取,并且正在逐个字符地读取它。我正在使用代码执行此操作:

ifstream plaintext (input.txt);
char ch;
if (plaintext.is_open())
{
    while(!plaintext.eof()){
        plaintext.get(ch);
        cout<<ch<<endl;
    }
    plaintext.close();
}

字符串“ABCDEFGHH”被打印出来。我不知道为什么它要打印两次'H'。任何帮助,将不胜感激。我从HERE得到这个代码示例

【问题讨论】:

  • Why is iostream::eof inside a loop condition considered wrong? 的可能重复项。链接中的示例代码很糟糕,从here发布的一本书中学习。
  • 啊,谢谢。我将代码更改为纯文本>> ch,它起作用了。我想我不需要使用 plaintext.get() 那么?
  • 这将跳过空格(除非您将其关闭),&gt;&gt; 用于格式化输入,这完全取决于您想要什么。 while (plaintext.get(ch)) 也可以工作,并且会读取文件的每个字节(除非您在 Windows 上并且文件以文本模式打开)。 is_open 检查也是多余的,因为如果文件未打开,流将失败,close 也是多余的,因为流在​​销毁时会自动关闭,所以整个示例可能是 for (char c; plaintext.get(c); ) std::cout.put(c); 甚至只是std::cout &lt;&lt; plaintext.rdbuf();

标签: c++ io char ifstream


【解决方案1】:

这是因为 EOF 测试并不意味着“我们的水晶球告诉我们此 Tream 中没有更多可用的字符”。相反,它是我们在输入操作失败后应用的测试,以确定输入是否由于数据不足 (EOF) 或其他情况(某种 I/O 错误)而失败。

换句话说,即使我们成功读取了最后一个字符,EOF 也可能为假。然后我们将尝试再次读取,这一次get 将失败,并且不会覆盖ch 的现有值,因此它仍然保留H

流无法预测数据的结束,因为它们不能用于通信设备,例如串行线路、交互式终端或网络套接字。在终端上,我们无法判断用户是否输入了他们将要输入的最后一个字符。在网络上,我们无法判断我们刚刚收到的字节是最后一个。相反,我们知道 previous 字节是最后一个字节,因为当前的读取操作失败了。

【讨论】:

  • 那么解决这个问题的方法是什么?
  • @AbhishekMane 解决方法是检查get操作是否失败。请注意问题中的程序如何忽略plaintext.get(ch) 的返回值。如果该操作失败,它只会在ch 中保留先前的值。由于没有检测到故障,程序员认为是新读取的值。
  • 试过std::cout&lt;&lt;plaintext.get(ch);,但给了Error :Invalid operands to binary expression ('std::ostream' (aka 'basic_ostream&lt;char&gt;') and 'std::basic_istream&lt;char&gt;::__istream_type' (aka 'basic_istream&lt;char&gt;'))
  • @AbhishekMane 尝试阅读有关 ifstream 的文档。大多数get 成员函数返回*thisifstream 本身。这可以作为布尔值进行测试,因为该类具有转换运算符。如果您尝试打印流,则不会使用该转换运算符。您必须明确使用它:cout &lt;&lt; bool(plaintext.get(ch)).
  • @AbhishekMane 我认为原因是ifstream 没有bool 过载,只有int。因此需要两次转换来选择重载:ifstreamboolboolint。 C++ 不会推断两个或多个隐式转换的链。
猜你喜欢
  • 2016-05-26
  • 1970-01-01
  • 2020-07-10
  • 2019-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多