【发布时间】:2021-10-31 15:03:54
【问题描述】:
我正在以这种方式读取 ascii 文件:name1|name2|name3|name4|name5|name6|name7||||||||||name8|||name9
它包含一堆由“|”分隔的名称char,一些插槽是空的。我正在使用以下代码来读取名称列表:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
int main() {
std::ifstream File;
File.open("File.txt");
if (!File.is_open())
return -1;
std::vector<std::string> Names;
char Buffer[0xff];
while (!File.getline(Buffer,16,'|').eof()) {
if (strlen(Buffer) == 0)
break;
Names.push_back(Buffer);
std::cout << strerror(File.rdstate()) << std::endl;
}
return 0;
}
它正在正常工作,它每次都会读取一个名称,但由于某种原因,如果它在File.getline() 的第二个参数上达到字符计数并且没有找到 delimiting 字符,它会自行关闭。这是我在具有大名称的文件上运行此代码后得到的控制台输出:
File: File.txt
Ana|Bjarne Stroustrup|Alex
Console:
No error
No such file or directory
它成功读取列表中的第一个名称,但是当它尝试读取第二个名称时,它没有命中 delimiting 字符,并且由于某种原因导致文件关闭本身。我希望有人能向我解释为什么会发生这种情况。
【问题讨论】:
-
您应该检查
getline和strlen函数调用之间的流状态。您可能想阅读以下内容:Why is iostream::eof inside a loop condition (i.e.while (!stream.eof())) considered wrong? -
寻求调试帮助的问题应提供minimal reproducible example 准确的输入、预期输出和实际输出。
-
The documentation 表示,如果
getline读取count-1字符并且没有遇到分隔符,则设置failbit。一旦流处于此失败状态,所有后续操作都会失败,直到该位被清除。 -
File.clear()。但问题是长名称的其余部分仍然在流中,以及它后面的分隔符,所以现在你需要弄清楚如何处理它。你为什么不使用the version of
getline,它需要std::string?它没有任何长度限制。特别是因为您最终将名称存储为std::string。 -
@Azazel:是的,新版本的代码更好。但是,我会将
while (!File.getline(Buffer,16,'|').eof()) {更改为while ( File.getline(Buffer,16,'|') ) {。这有两个优点:它更简单,并且它还可以在错误条件下停止循环,而不仅仅是文件结束条件。