[英]getline setting failbit along with eof
我知道这种行为的起源,因为它在SO中的多个帖子中得到了很好的解释,一些值得注意的例子是:
为什么循环条件中的iostream :: eof被认为是错误的?
它也包含在std::getline
标准中 :
3)如果由于某种原因没有提取任何字符(甚至没有丢弃的分隔符),getline设置failbit并返回。
我的问题是如何处理这种行为,你希望你的流为所有情况捕获一个failbit
异常,除了由于到达eof
而导致的最后一行空文件。 有什么明显的东西让我失踪吗?
MWE:
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
void f(const std::string & file_name, char comment) {
std::ifstream file(file_name);
file.exceptions(file.failbit);
try {
std::string line;
while (std::getline(file, line).good()) {
// empty getline sets failbit throwing an exception
if ((line[0] != comment) && (line.size() != 0)) {
std::stringstream ss(line);
// do stuff
}
}
}
catch (const std::ios_base::failure& e) {
std::cerr << "Caught an ios_base::failure.\n"
<< "Explanatory string: " << e.what() << '\n'
<< "Error code: " << e.code() << '\n';
}
}
int main() {
f("example.txt", '#');
}
其中example.txt是制表符分隔的文件,其最后一行只是\\n
char:
# This is a text file meant for testing
0 9
1 8
2 7
while(std::getline(file, line).good()){...}
复制问题。
编辑:我误解了OP,请参阅David的上述答案。 此答案用于检查文件是否具有终止换行符。
在while (getline)
循环结束while (getline)
,检查file.eof()
。
假设你刚刚为文件的最后一行做了std::getline()
。
如果后面有\\n
,那么std::getline()
已经读取了分隔符并且没有设置eofbit
。 (在这种情况下,下一个std::getline()
将设置eofbit
。)
然而,如果它之后没有\\n
,那么std::getline()
已经读取了EOF并且确实设置了eofbit
。
在这两种情况下,下一个std::getline()
将触发failbit
并输入您的异常处理程序。
PS:行if ((line[0] != comment) && (line.size() != 0)) {
如果line
为空则为UB。 条件的顺序需要颠倒。
避免设置failbit
另一种方法是简单地重构if
测试以检测空行的读取。 由于这是你在这种情况下的最后一行,你可以简单地return
以避免抛出错误,例如:
std::ifstream file (file_name);
file.exceptions (file.failbit);
try {
std::string line;
while (std::getline(file, line)) {
// detect empty line and return
if (line.size() == 0)
return;
if (line[0] != comment) {
std::stringstream ss(line);
// do stuff
}
}
}
...
另一种方法是检查eofbit
是否设置为catch
。 如果设置了eofbit
- 读取成功完成。 例如
catch (const std::ios_base::failure& e) {
if (!file.eof())
std::cerr << "Caught an ios_base::failure.\n"
<< "Explanatory string: " << e.what() << '\n'
<< "Error code: " /* << e.code() */ << '\n';
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.