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