为啥 eof() 永远不会返回 true?

Posted

技术标签:

【中文标题】为啥 eof() 永远不会返回 true?【英文标题】:Why is eof() never returning true?为什么 eof() 永远不会返回 true? 【发布时间】:2016-02-08 09:49:18 【问题描述】:

我正在尝试让我的程序从数据 (.dat) 文件(实际上只是一个文本文件)中读取数据。所以当然我正在使用循环条件while(!file.eof()),但这永远不会返回true。这是我的功能:

void Table::readIn(const char finput[])
    std::ifstream file;

    file.open(finput);

    if (!file.is_open())
    
        std::cout << "Cannot open " << finput << std::endl;
        return;
    
    char key[100];
    file.get(key, 99, '\n');
    while (!file.eof())
    
        stock * item = new stock;
        item->setTick(key);
        file.get(key, 99, '\n');
        item->setName(key);
        file.get(key, 99, '\n');
        item->setValue(atof(key));
        file.get(key, 99, '\n');
        item->setDate(key);
        file.get(key, 99, '\n');
        item->setYearReturn(atof(key));
        file.get(key, 99, '\n');
        addStock(item);
    

这是我的数据文件中的内容:

TSLA
Tesla Motors, Inc.
30160000000
November 6, 2015
13.1

我希望我能给你们更多信息,但程序无限期地循环通过while (!file.eof()) 循环这一事实是我对这个问题的全部了解。

编辑:我通过调试器运行它,在while 循环的每一行都有一个断点。我发现第一个get() 调用(在while 循环之前)将key 设置为正确的值,但之后的每个get() 调用都将key 设置为""。我假设这是因为程序从不读取文件中的第一个 '\n' 字符。你们知道如何解决这个问题吗?

编辑 2:这个问题与 Why is iostream::eof inside a loop condition considered wrong? 不同,因为每次运行 while 循环时,我都必须阅读不止一行。

【问题讨论】:

首先,eofbit 标志在您尝试从文件末尾之外读取之前不会设置,这意味着您的循环不会像您期望的那样工作。要继续,请尝试在调试器中逐行执行代码,您的阅读也不会像您预期的那样工作。 @JoachimPileborg 好的,第一个get() 调用(在while 循环之前)将key 设置为正确的值,但之后的每个get() 调用都将key 设置为“”。我假设这是因为程序从不读取文件中的第一个 '\n' 字符。你知道我会怎么解决这个问题吗? 最简单的解决方案?使用std::stringstd::getline 读取行数。 “所以我当然使用循环条件 while(!file.eof())”——这是不正确的…… @LarryK - 在你解决了file.get() 问题之后,while (!file.eof()) 仍然是错误的(即使这不是你问的问题)。 【参考方案1】:

您必须将这一行 while (!file.eof()) 替换为

while (true)
    
        /*code*/
        file.get(key, 99, '\n');
        if (file.eof())  break;  // and similarly for other usages where you are reading the stream
        /*code*/
    

编辑: 好的。看起来你的问题就在这里,引用documentation of ifstream::get:

下一个可用的输入字符 c 等于 delim,由 Traits::eq(c, delim) 确定。未提取此字符

因此,在每次调用 get 之后,您的搜索指针仍指向分隔符。所以在第一次调用之后,get 不断遇到换行符,因此返回一个空数据。您可以添加一个虚拟读取来使用该分隔符,或者更好地使用getline

【讨论】:

这并没有解决问题。 @LarryK 你能用你所做的改变更新代码吗? 为什么你会期望它比他拥有的更好?除非他清除错误标志,否则文件不会从 eof 状态变为非 eof 状态。【参考方案2】:

您使用std::istream::get 的问题在于它不使用分隔符。第一次调用它会正常工作,但是下一次调用会立即看到前一次调用留下的换行符,并且不会读取任何内容。

如果您想读取行,请使用std::istream::getline(如果您坚持使用字符数组)或std::getlinestd::string,这是我的建议。


您也不需要明确的eof 检查,而是依赖于所有函数都返回(引用)流并且流可以是used directly in conditions 的事实,例如

if (!std::getline(...))
    // end of file or error

【讨论】:

我收到Error: getline() is undefined 假设我在编辑 3 之前拥有的代码,我能够通过将我的每个 file.get() 调用替换为 file.getline 调用来解决此问题。您应该更新您的答案以指定这一点(因为getline() 会丢弃输入流中的分隔符,而get() 不会)。 @LarryK:std::getline&lt;string&gt; 中。您必须包含该标头才能使用它。 @LarryK 并将正确的参数也传递给std::getline @ChristianHackl 我用的是std::istream::getline,而不是std::getline

以上是关于为啥 eof() 永远不会返回 true?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 HTTP 请求永远不会通过异步等待返回?

从 PHP 控制器使用 request.post() 调用 python 脚本永远不会返回。为啥?

Swift 5.2 UIAccessibility.isAssistiveTouchRunning 永远不会返回 true,也不会触发 UIAccessibility.assistiveTouchSt

当我第一次隐藏元素时,如果语句永远不会返回 true

Request.IsAjaxRequest 在 MVC3 中永远不会返回 true

为啥 Asp.Net Core Kestrel 服务器向 Ngrok 返回 404 并且控制器永远不会被调用?