【问题标题】:Detect if iterator is last element of std::map检测迭代器是否是 std::map 的最后一个元素
【发布时间】:2016-02-12 23:14:57
【问题描述】:

这类似于this question,但不是重复的。我正在尝试遍历地图并打印每个元素的值,但最后一个元素的输出略有不同。在那个问题中,他们建议使用map.rbegin().base(),但这对我不起作用。

这是我的代码:

#include <iostream>
#include <map>

int main()
{
    std::map <char, int> charMap = { {'a', 1}, {'b', 2}, {'c', 3}, {'d', 4} };
    for (auto iter = charMap.begin(); iter != charMap.end(); iter++)
    {
        std::cout << iter->first << ":\t" << iter->second;
        if (iter == charMap.rbegin().base())
            std::cout << "\t//This is the last element.\n";
        else
            std::cout << "\n";
    }
}

我希望我的输出如下所示:

a:    1
b:    2
c:    3
d:    4    //This is the last element. 

但是,相反,我得到了这个输出:

a:    1
b:    2
c:    3
d:    4    

现在我意识到有更好的方法可以做到这一点,但我希望这也能奏效。为什么我不能比较itercharMap.rbegin().base()

【问题讨论】:

  • 请注意,在这种情况下,通常很容易重写循环体,以便对第一个而不是最后一个元素进行特殊处理。
  • @ChristianHackl 注意,这显然不是这里的情况 :)
  • @BartoszKP:为什么不呢?除了第一行以外的每一行都以换行符开始,将“这是最后一个元素”放在循环之后。
  • @ChristianHackl 你是对的,但是 OP 确实意识到了这一点,并且问题是专门针对流程的。

标签: c++ dictionary iterator std


【解决方案1】:

使用来自&lt;iterator&gt;std::next作为

if (std::next(iter) == charMap.end())
    std::cout << "\t//This is the last element.\n";

改为。

【讨论】:

  • 哦,我使用了一个单独的迭代器,然后递增那个迭代器。很高兴了解 std::next();
  • 从 C++11 开始有效
  • 检查一个元素是否是最后一个元素比使用反向迭代器要好,因为反向迭代器的逻辑很奇怪。它为std::vector 解决了我的问题。
【解决方案2】:

base() 方法将迭代器返回到跟随反向迭代器指向的元素的元素。这意味着rbegin().base() 等价于end()

要完成你的任务,你可以这样做:

#include <iostream>
#include <map>

int main()
{
    std::map <char, int> charMap = { {'a', 1}, {'b', 2}, {'c', 3}, {'d', 4} };
    for (auto iter = charMap.begin(); iter != charMap.end(); )
    {
        std::cout << iter->first << ":\t" << iter->second;
        if (++iter == charMap.end())
            std::cout << "\t//This is the last element.\n";
        else
            std::cout << "\n";
    }
}

【讨论】:

    【解决方案3】:

    因为std::reverse_iterator 存储了偏移量为1 的迭代器,所以charMap.rbegin().base() == charMap.end()here 上方的图表说明了这一点。

    您应该改用std::prevstd::next 中的&lt;iterator&gt;

    iter == std::prev(charMap.end())
    

    std::next(iter) == charMap.end()
    

    你觉得哪个更有意义。

    【讨论】:

      【解决方案4】:

      base() 不返回相同的元素:

      基迭代器指的是下一个元素(从std::reverse_iterator::iterator_type perspective)到reverse_iterator 当前指向的元素。那是&amp;*(rit.base() - 1) == &amp;*rit

      这按预期工作:

      #include <iostream>
      #include <map>
      
      int main()
      {
          std::map <char, int> charMap = { {'a', 1}, {'b', 2}, {'c', 3}, {'d', 4} };
          auto last = charMap.rbegin();
          ++last;
      
          for (auto iter = charMap.begin(); iter != charMap.end(); iter++)
          {
              std::cout << iter->first << ":\t" << iter->second;
              if (iter == last.base())
                  std::cout << "\t//This is the last element.\n";
              else
                  std::cout << "\n";
          }
      }
      

      【讨论】:

        【解决方案5】:

        实际上,这并不期望工作,因为iter 确实与charMap.rbegin().base() 不同。

        您的逻辑是正确的,唯一的问题是 charMap.rbegin().base() 迭代器等于 charMap.end(),但是您在 iter 达到 charMap.end() 值的那一刻离开了 for 语句,所以它从来没有机会在 for 循环中的 if 语句中对其进行测试。

        要使其工作,您可以按以下方式重写 if 语句:

        if (iter->first == charMap.rbegin()->first)
            std::cout << "\t//This is the last element.\n";
        else
            std::cout << "\n";
        

        因此,您将比较映射键而不是迭代器本身。

        【讨论】:

          【解决方案6】:

          丑陋的。 . .但 。 . .

              auto iterCpy = iter;
              if (++iterCpy == charMap.end())
                  std::cout << "\t//This is the last element.\n";
          

          使用 vsoftco 的答案 :)

          【讨论】:

            【解决方案7】:

            这是有效的:

            #include <iostream>
            #include <map>
            
            int main()
            {
                std::map <char, int> charMap = { {'a', 1}, {'b', 2}, {'c', 3}, {'d', 4} };
                for (auto iter = charMap.begin(); ;)
                {
                    std::cout << iter->first << ":\t" << iter->second;          
                    if (++iter== charMap.end()){
                        std::cout << "\t//This is the last element.\n"; break;
                    }
                    else
                        std::cout << "\n";
                }
            
            }
            

            【讨论】:

              猜你喜欢
              • 2016-10-31
              • 2011-02-10
              • 2011-08-30
              • 1970-01-01
              • 1970-01-01
              • 2019-04-08
              • 2021-08-24
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多