我最初构建一个类似索引的机制,使用getline读取文本文件的每一行,检查它是否与已知的头部声明(string.compare)匹配,并将tellg位置保存为该点的索引 . 我的意图是使用seekg(index,ios :: beg)来寻找 Headers 所在文件中的位置 . 在构建索引并调用seekg(0,ios :: beg)之后读取文件一次后,下一个getline返回一个空字符串,我希望看到文件中的第一行 .
我的代码的一部分在下面,以更好地突出我的问题
//build the index
while (! m_fileIn.eof())
{
getline (m_fileIn,lineRead);
int lineID = getLineID(lineRead);
if(lineID==1) //if its an STRM
{
//save the index
}
}
// start reading the file data
m_fileIn.seekg(0,ios::beg);
//read first line (title)
getLineID函数返回一个int,具体取决于字符串比较的结果 .
如果我需要重新读取文件,是否使用getline不正确?
2 回答
在这里发布并拖网各种网站后,我添加了该行
在线之前
通过清除错误标志(我假设eof错误)我能够正常继续 .
马丁 - 我真的很想知道更多关于我在不知不觉中使用的反模式,我已经更新了我的代码以包含你的更改,非常感谢 .
您的问题是由于您在流中设置了错误位而导致的 .
在重置坏位之前,将忽略对流的操作 .
注意:坏位是许多错误条件之一,包括EOF
但这不是你的主要问题:
您正在使用
Classic anti pattern
来读取文件:而是使用它 .
问题是EOF在您阅读之前未设置 .
最后一次有效读取读取UPTO但未超过EOF(因此未设置EOF) .
因此,请考虑您已阅读文件中最后一行的情况 . EOF尚未设置,因为您没有读过它 . 所以循环进入 . 您现在执行getline() . 这会尝试读取过去的EOF,因为绝对没有要读取的数据(不是单个字节) . 所以getline()现在失败,你现在使用lineRead调用getlineID(),其值是不确定的(标准没有说明当EOF条件被击中时lineRead会发生什么;但它可能有最后一行读取的值,因为你似乎没有在循环内重置它) .
此代码的另一个问题是它只检查EOF . 发生其他类型的错误会发生什么?循环实际上陷入无限循环;这是因为当设置错误标志时不再发生读取,因此您永远无法达到EOF .
解决方案是在while循环测试中执行读取操作 . 这是有效的,因为getline()返回作为第一个参数传递的流 . 因此,流在布尔上下文中使用 . 当在布尔上下文中使用流时,它将转换为可用作布尔值的类型;如果没有错误,则此对象的值等效,否则为false .
在这种情况下,尝试读取,但如果失败,则永远不会进入循环 .