为啥 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::string
和std::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::getline
和std::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
在<string>
中。您必须包含该标头才能使用它。
@LarryK 并将正确的参数也传递给std::getline
。
@ChristianHackl 我用的是std::istream::getline
,而不是std::getline
。以上是关于为啥 eof() 永远不会返回 true?的主要内容,如果未能解决你的问题,请参考以下文章
从 PHP 控制器使用 request.post() 调用 python 脚本永远不会返回。为啥?
Swift 5.2 UIAccessibility.isAssistiveTouchRunning 永远不会返回 true,也不会触发 UIAccessibility.assistiveTouchSt