1

我最初正在构建一个类似索引的机制,使用 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 的使用是否不正确?

4

2 回答 2

2

您的问题是因为您在流中设置了 Bad 位。
流上的操作将被忽略,直到 Bad 位被重置。

// 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() 返回作为第一个参数传递的流。因此,流在布尔上下文中使用。当流在布尔上下文中使用时,它被转换为可用作布尔值的类型;如果没有错误,则此对象的值等效为 true,否则为 false。

在这种情况下,会尝试读取,但如果失败,则永远不会进入循环。

于 2010-08-31T12:14:22.317 回答
1

在此处发布并搜索各种网站后,我添加了该行

m_fileIn.clear();

行前

getline (m_fileIn,lineRead);

通过清除错误标志(我假设 eof 错误)我能够正常继续。

Martin - 我真的很想了解更多关于我在不知不觉中使用的反模式的信息,我已经更新了我的代码以包含您的更改,非常感谢。

于 2010-08-31T12:31:32.827 回答