2

我想打印出多重集中的每个重复项,但不知何故迭代器对我来说表现得很奇怪。如何修复此代码?这段代码导致了一个永远的循环,这让我感到惊讶。

#include <set>
#include <iostream>
#include <sstream>

static void print_duplicate(const std::multiset<int>& mset)
{
  std::stringstream error_msg;
  for (auto it = mset.begin(); it != mset.end(); ++it)
    {
      unsigned count = mset.count(*it);
      if (count < 2)
        continue;

      error_msg << "Duplicated numbers found:\n";

      for (unsigned i = 0; i < count; ++it, ++i)
        error_msg << "\tNum:" << *it << "\n";
    }

  std::cout << error_msg.str();
}

int main()
{
  std::multiset<int> mset;

  // fill it
  mset.insert(1);
  mset.insert(1);
  mset.insert(1);

  print_duplicate(mset);
}

编辑 我在周期结束时添加了一个 --it

  for (unsigned i = 0; i < count; ++it, ++i)
    error_msg << "\tNum:" << *it << "\n";
  --it; // this line fix it
}
4

5 回答 5

3

在您的外部循环内,您可能会增加it不止一次。因此,条件it != mset.end()可能永远不会为真,因为结尾已经被跳过。增加一个过去的迭代器是未定义的行为,这意味着它也可能静默失败。

一个可能的解决方案可能是也检查it != mset.end()内部for循环:

for (unsigned i = 0; (i < count) && (it != mset.end()); ++it, ++i)
    error_msg << "\tNum:" << *it << "\n";
于 2012-11-30T14:08:23.477 回答
3

for (unsigned i = 0; i < count; ++it, ++i)当此循环结束时,it将等于,mset.end()并且由于您仍然拥有++it主循环中的另一个,因此您将得到不同的东西,mset.end()因此程序永远不会结束。

于 2012-11-30T14:08:32.527 回答
2

问题似乎是您在没有发现的情况下滑过了终点。在mset你创建的,只有1s。这意味着count将是 3 并且嵌套for(一个 over i)将执行 3 次;当它完成时,it将等于mset.end()。然后控制到达外部的末尾forit递增,变得非法,更重要的是,不同于mset.end(). 这意味着外循环永远不会终止。

于 2012-11-30T14:08:33.787 回答
1

快速修复:在内循环之后添加一个额外的行:it--;

Angew 的回答中解释了原因。

于 2012-11-30T14:19:28.567 回答
0

将 for 循环更改为:

for(std::container::iterator it=mset.begin(), it_next=it; it!=mset.end(); it=it_next) {
  ++it_next;
  ...
}

本质上,您正在跳过循环的末尾,因为您正在根据迭代器检查变量。仅增加辅助迭代器将防止这种情况发生。

于 2012-11-30T14:11:17.593 回答