从文本文件中读取时使用getline

时间:2010-08-31 11:53:37

标签: c++ ifstream getline

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

2 个答案:

答案 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 - 我真的很想知道更多关于我在不知情的情况下使用的反模式,我已经更新了我的代码以包含您的更改,非常感谢。