寻找cin和ifstream的流结束位置?

7

我正在运用一本C++教科书作为C++编程的复习。其中一个练习问题(不想过多解释)要求我定义一个函数,该函数可以将ifstream或cin(例如,istream)作为参数传递。然后,我必须读取流。问题是,我无法找到一种方法使这个函数使用cin和ifstream有效地查找流的末尾。换句话说,

while(input_stream.peek() != EOF)

对于 cin,这种方法行不通。我可以重新设计函数,查找特定短语(比如“# End of Stream #”之类的),但如果我传递的文件流恰好有这个短语,那么这样做是不好的。

我考虑使用函数重载,但到目前为止,书上还没有提到要我这样做。我可能在这一个练习问题上花费了太多精力,但我喜欢创造性的过程,并且很想知道是否有一种方法可以在不使用重载的情况下完成这个问题。


请查看此问题:https://dev59.com/I3A75IYBdhLWcg3wm6ix - Archie
3个回答

6

eof()函数适用于cin。如果你的代码出现问题,请贴出来让我们帮助你。一个常见的错误是在尝试读取流结束后,eof标志被设置。

以下是演示:

#include <iostream>
#include <string>

int main( int, char*[] )
{
    std::string s;
    for ( unsigned n = 0; n < 5; ++n )
    {
        bool before = std::cin.eof();
        std::cin >> s;
        bool after = std::cin.eof();
        std::cout << int(before) << " " << int(after) << "  " << s << std::endl;
    }

    return 0;
}

以及它的输出:

D:>t
aaaaa
0 0  aaaaa
bbbbb
0 0  bbbbb
^Z
0 1  bbbbb
1 1  bbbbb
1 1  bbbbb

(在Windows上使用Ctrl-Z,在许多其他操作系统上使用Ctrl-D可以生成EOF)

抱歉之前有些混淆,我最初写的是while(!input_stream.eof()),但后来意识到我应该写成while(input_stream.peek != EOF)。不过无论如何,这两种方法都可以使用control+z(有趣的是,我刚刚在维基百科上读到了eof字符)。感谢atzz和大家的帮助! - user435219
最好将流转换为布尔值,而不是使用.eof.bad - Mooing Duck

2
如果在布尔上下文中使用流,则如果它尚未达到EOF,它将转换为等效于true的值,如果尝试从EOF后读取,则转换为false(如果以前读取流时出现错误,则也为false)。
由于大多数流上的IO操作返回流本身(因此它们可以链接)。您可以执行读取操作并在测试中使用结果(如上所述)。
因此,一个从流中读取数字的程序:
int main()
{
   int x;

   // Here we try and read a number from the stream.
   // If this fails (because of EOF or other error) an internal flag is set.
   // The stream is returned as the result of operator>>
   // So the stream is then being used in the boolean context of the while()
   // So it will be converted to true if operator>>  worked correctly.
   //                         or false if operator>> failed because of EOF
   while(std::cin >> x)
   {
       // The loop is only entered if operator>> worked correctly.
       std::cout << "Value: " << x << "\n";
   }

   // Exit when EOF (or other error).
}

2

为什么 std::cin.eof() 不起作用?cin 在标准输入关闭时会发出EOF信号,这会在用户使用 Ctrl+d (*nix) 或 Ctrl+z (Windows),或者(在管道输入流的情况下)当管道文件结束时发生。


1
在Windows中是Ctrl+Z,而在基于UNIX的系统中是Ctrl+D - Archie
啊,那确实可以(至少在Windows上是Ctrl + Z)。抱歉,如果有点混淆,因为我最初在帖子中使用了while(!input_stream.eof()),后来将其编辑为while(input_stream.peek() != EOF)。无论如何,我对使用while(!input_stream.eof())的一个担忧是,当函数读取EOF字符时,输入流的失败位被设置。这应该发生吗? - user435219
@user435219:是的,因为它无法读取数据,因为已经到达了文件尾(EOF)。几乎总是会触发“失败(fail)”。 - Mooing Duck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接