std::getline 在遇到 eof 时抛出
Posted
技术标签:
【中文标题】std::getline 在遇到 eof 时抛出【英文标题】:std::getline throwing when it hits eof 【发布时间】:2012-08-02 05:10:08 【问题描述】:std::getline
在获得eof
时抛出异常。
我就是这样做的。
std::ifstream stream;
stream.exceptions(std::ifstream::failbit|std::ifstream::badbit);
try
stream.open(_file.c_str(), std::ios_base::in);
catch(std::ifstream::failure e)
std::cout << "Failed to open file " << _file.c_str() << " for reading" << std::endl;
while(!stream.eof())
std::string buffer = "";
std::getline(stream, buffer);
//process buffer
//I do also need to maintain state while parsing
在上面的代码中,getline
在得到eof
时抛出异常
这种情况如何处理?
编辑
std::string buffer = "";
while(std::getline(stream, buffer))
//also causes getline to hit eof and throw
【问题讨论】:
旁注:循环的结构不正确,因为您需要在std::getline()
之后立即检查eof()
。
您要求例外。点击eof
后,流处于bad
状态。
Why is iostream::eof inside a loop condition considered wrong?
'如何处理这种情况'。这取决于你想做什么,你没有很好地解释自己。你不想有例外吗?你想捕捉异常吗?如果你想捕捉它,接下来你想发生什么?请解释您要做什么。
【参考方案1】:
您在代码的最开头激活流的异常处理:
stream.exceptions(std::ifstream::failbit|std::ifstream::badbit);
现在如果浮点值、整数或字符串等格式化数据的提取失败,它将设置失败位:
eofbit 表示输入操作已到达结束 输入序列; failbit 表示输入操作未能读取预期的 字符,或输出操作未能生成 想要的字符。
虽然getline(stream,buffer)
确实会在到达文件末尾时设置eofbit
,但它也会设置故障位,因为无法提取所需的字符(一行)。
要么在循环周围包装另一个 try-catch-block,要么禁用 failbit 异常。
示例:
#include <iostream>
#include <fstream>
int main()
std::ifstream stream("so.cc");
stream.exceptions(std::ifstream::failbit|std::ifstream::badbit);
std::string str;
try
while(std::getline(stream, str));
catch(std::ifstream::failure e)
std::cerr << "Exception happened: " << e.what() << "\n"
<< "Error bits are: "
<< "\nfailbit: " << stream.fail()
<< "\neofbit: " << stream.eof()
<< "\nbadbit: " << stream.bad() << std::endl;
return 0;
结果:
发生异常:basic_ios::clear 错误位是: 故障位:1 eofbit: 1 坏比特:0
请注意,两者 eofbit
和 failbit
均已设置。
另见:
std::ios_base::iostate
第 27.5.3.1.5 节中的表 124(见上文)
【讨论】:
那么我应该在getline
周围放置一个静默catch 块吗?
如果你使用getline(std::istream,std::string)
,那么它无法提取字符串的唯一原因就是EOF。我建议您实际上禁用在std::ifstream::failbit
上引发异常。当然,您可以使用静默 catch 块。处理这类事情的方法有很多,选择最适合自己的。
我希望getline
将流读入缓冲区,只要它不获取eof. once it fails due to
eof` 我希望控件低于getline
,因为我有前几行的状态保留以前的迭代。【参考方案2】:
如您所说,当流当前位于文件末尾的空白行时调用 getline 将同时设置 eofbit(因为它到达文件末尾)和 failbit(因为无法提取任何内容,甚至行分隔符)。
因此,如果您已将流设置为在设置 failbit 时引发异常,则在读取该空白行时会引发异常。
为了防止这种情况,您可以在调用 getline 之前查看流中的下一个字符:
std::string buffer = "";
while(stream.peek() != EOF && std::getline(stream, buffer))
//do something with the buffer
【讨论】:
以上是关于std::getline 在遇到 eof 时抛出的主要内容,如果未能解决你的问题,请参考以下文章
我在 Flutter 中遇到了一个问题:在构建 TextField 时抛出了以下断言,它使我遇到了一个奇怪的问题