检测迭代器是否是std::map的最后一个元素

Detect if iterator is last element of std::map

本文关键字:最后一个 元素 map 检测 是否是 std 迭代器      更新时间:2023-10-16

这与这个问题类似,但不是重复的。我试图遍历映射并打印每个元素的值,但最后一个元素的输出略有不同。在这个问题上,他们建议使用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()

使用<iterator>中的std::next作为

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

相反。

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";
    }
}

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

您应该使用<iterator>:中的std::prevstd::next

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

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

无论你觉得哪个更有意义。

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

基迭代器指的是reverse_iterator当前指向的元素的下一个元素(从std::reverse_iterator::iterator_type perspective开始),即&*(rit.base() - 1) == &*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";
    }
}

实际上,由于itercharMap.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";

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

丑陋。但是

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

使用vsoftco的答案:)

这是有效的:

#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";
    }
}