C ++列表删除重复字符串

时间:2011-01-20 15:40:25

标签: c++ list unique

使用列表时遇到一些问题。

我拥有的东西:我正在从聊天框中读取新的文字行。 我总是从框中取出最后20行,然后我想将它们与之前提取的所有行进行比较。如果发现新行,则将其发送到外部函数,该函数反汇编该行以进行进一步处理。在我使用数组和向量之前,列表似乎是更好的方法。

我的想法:我有一个名为usedlines的列表,其中包含所有旧的已使用的行。 fetchedLines列表包含从聊天框中提取的最新20行。

不,我只想循环使用它们来查明所获取的行是否包含之前未见过的新行。在循环之后,fetchedlines中的遗留物被处理到下一个函数。

问题:当我循环通过这个循环时,我会在一段时间后得到一个错误的指针。为什么? 额外奖励:有没有人有更好的想法来解决这个问题?

typedef list<string> LISTSTR;
LISTSTR::iterator f;
LISTSTR::iterator u;
LISTSTR fetchedlines;                 
LISTSTR usedLines;                



fetchedlines.insert(fetchedlines.end(), "one");
fetchedlines.push_back("two");
fetchedlines.push_back("three");
fetchedlines.push_back("four");
fetchedlines.push_back("three");

usedLines.push_back("three");
usedLines.push_back("blää");
usedLines.push_back("lumpi");
usedLines.push_back("four");


 for (u =  usedLines.begin(); u != usedLines.end(); u++)
 {
 for (f =  fetchedlines.begin(); f != fetchedlines.end(); f++)
   {
   if(*u==*f)
    fetchedlines.remove(*f);
  }

}

6 个答案:

答案 0 :(得分:5)

fetchedlines.remove(*f)的调用使迭代器无效。

编辑:

您遇到的问题的一种可能解决方案是,只需迭代usedLines并删除fetchedlines中包含的所有元素。

for (u = usedLines.begin() u != usedLines.end(); u++)
    fetchedLines.remove(*u);

//Process all of fetchedLines

答案 1 :(得分:3)

你得到一个错误的原因是fetchedlines.remove(* f)修改了fetchedlines,如果它是最后一个元素,那么for循环增加太多了

尝试这样的事情:

for (u = userLines.begin (); u != usedLines.end (); ++u)
{
    for (f = fetchedlines.begin (); f != fetchedlines.end ();)
    {
        if (*u == *f)
        {
            f = fetchedlines.erase (f);
        }
        else
        {
            ++f;
        }
    }
}

(当然不是解决这是否是解决问题的好方法)

答案 2 :(得分:2)

当您正在迭代时,您正在从fetchedlines中删除元素。

这就是你得到一个坏指针的原因。

答案 3 :(得分:2)

在迭代它时,绝不能修改列表(或几乎任何其他容器)。那是你当前的问题。

一个更有趣的问题是为什么你这样做是为了这样做。是不是有办法在线上获得序列号,或者可能是时间戳,所以你可以只比较那些?

答案 4 :(得分:0)

因为* f是一个指向你刚删除的元素的迭代器。

尝试以下方法:

if(*u==*f)
{
    LISTSTR::iterator t = f;;

    f--;
    fetchedlines.remove(*t);
}

作为旁边,删除在列表中搜索与迭代器f指向的数据匹配的内容。如果你想简单地摆脱指向的数据,你最好不要做

f = fetchedlines.erase( f );
f--;

答案 5 :(得分:0)

可以使用list::remove_if和lambda表达式完成此操作。此方法仍然是两个嵌套循环,但它们隐藏在函数调用中。对于小型列表而言,这可能足够快,但不能很好地扩展。如果对数据进行排序或使用了有序容器,则可能会快得多。

fetchedLines.remove_if([&](std::string &str)
{
    return std::find(usedLines.begin(), usedLines.end(), str) != usedLines.end();
});