Reputation: 7669
This is similar to this question but not a duplicate. I'm trying to iterate through a map and print the values of each element, but with slightly different output on the last element. In that question, they recommend using map.rbegin().base()
, but it's not working for me.
Here is my code:
#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";
}
}
I'd expect my output to look like this:
a: 1
b: 2
c: 3
d: 4 //This is the last element.
But instead, I am getting this output:
a: 1
b: 2
c: 3
d: 4
Now I realize that there is a better way to do this, but I would expect this to work also. Why can't I compare iter
and charMap.rbegin().base()
?
Upvotes: 10
Views: 11796
Reputation: 7851
This is working:
#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";
}
}
Upvotes: 0
Reputation: 27
Actually, this is not expect to work as iter
is indeed different from charMap.rbegin().base()
.
Your logic is correct, the only problem is that charMap.rbegin().base()
iterator is equal to charMap.end()
, but you leave your for statement at the moment iter
reaches the charMap.end()
value, so it never got the chance to test it in the if statement inside the for loop.
To make it work you could rewrite the if statement in the following way:
if (iter->first == charMap.rbegin()->first)
std::cout << "\t//This is the last element.\n";
else
std::cout << "\n";
So you will be comparing the map key instead of the iterator itself.
Upvotes: 1
Reputation: 13486
Because std::reverse_iterator
stores iterator with offset of 1
, so that charMap.rbegin().base() == charMap.end()
. Chart over here illustrates this.
You should instead use std::prev
or std::next
from <iterator>
:
iter == std::prev(charMap.end())
or
std::next(iter) == charMap.end()
Whichever you find more meaningful.
Upvotes: 4
Reputation: 35891
base()
doesn't return the same element:
The base iterator refers to the element that is next (from the
std::reverse_iterator::iterator_type perspective
) to the element thereverse_iterator
is currently pointing to. That is&*(rit.base() - 1) == &*rit
.
This works as intended:
#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";
}
}
Upvotes: 2
Reputation: 481
base()
method returns iterator to an element that follows the element to which a reverse iterator is pointing. This means that rbegin().base()
is equivalent to end()
To accomplish your task, you can do this:
#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";
}
}
Upvotes: 5
Reputation: 56547
Use std::next
from <iterator>
as
if (std::next(iter) == charMap.end())
std::cout << "\t//This is the last element.\n";
instead.
Upvotes: 17
Reputation: 16195
Ugly . . . but . . .
auto iterCpy = iter;
if (++iterCpy == charMap.end())
std::cout << "\t//This is the last element.\n";
use vsoftco's answer :)
Upvotes: 0