它比您描述的要简单。前两个步骤很好(但如果您遵循我的其余建议,则不需要第二个步骤)。然后您应该尝试提取,但将提取用作循环或if
语句的条件。例如,如果文件被格式化为一系列相同格式的行(或其他分隔序列),您可以这样做:
std::string line;
while (std::getline(i, line)) {
// Parse line
}
只有当行提取有效时,循环体才会执行。当然,您需要检查循环内行的有效性。
如果您要对流进行特定系列的提取或其他操作,则可以将它们置于如下if
条件:
if (i >> some_string &&
i.get() == '-' &&
i >> some_int) {
// Use some_string and some_int
}
如果第一次提取失败,则i.ignore()
由于 的短路评估而无法执行&&
。只有当两次提取都成功时,语句的主体if
才会执行。如果你有两个提取在一起,你当然可以链接它们:
if (i >> some_string >> some_int) {
// Use some_string and some_int
}
如果第一次失败,链中的第二次提取将不会发生。提取失败会使流处于所有后续提取也自动失败的状态。
出于这个原因,也可以将流操作放在if
条件之外,然后检查流的状态:
i >> some_string >> some_int;
if (i) {
// Use some_string and some_int
}
使用这两种方法,您不必检查流的某些问题。检查流eof()
并不一定意味着下一次读取将失败。一个常见的情况是人们使用以下不正确的提取循环:
// DO NOT DO THIS
while (!i.eof()) {
std::getline(i, line)
// Do something with line
}
大多数文本文件都以文本编辑器隐藏的额外新行结尾。当您从文本文件中读取行时,对于最后一次迭代,您还没有到达文件末尾,因为还有 a\n
需要读取。所以循环继续,尝试提取下一行不存在并搞砸了。人们经常将此视为“两次读取文件的最后一行”。