Determine if the iterator is the last element of std :: map

This is similar to this question , but not a duplicate. I am trying to iterate over a map and print out the values โ€‹โ€‹of each element, but with a slightly different output on the last element. In this question, they recommend using map.rbegin().base() , but it does not work 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 expect my output to look like this:

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

But instead, I get this output:

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

Now I understand that there is a better way to do this, but I expect this to work too. Why can't I compare iter and charMap.rbegin().base() ?

+5
source share
7 answers

base() method returns to the iterator the element that follows the element that the inverse iterator points to. This means that rbegin().base() 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"; } } 
+4
source

Use std::next from <iterator> as

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

instead.

+10
source

Because std::reverse_iterator stores the iterator with offset 1 , so charMap.rbegin().base() == charMap.end() . The diagram above illustrates this.

Use std::prev or std::next from <iterator> instead:

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

or

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

Depending on what you find more meaningful.

+3
source

base() does not return the same element:

The base iterator refers to the next element (from std::reverse_iterator::iterator_type perspective ) to the element pointed to by reverse_iterator . This 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"; } } 
+2
source

Ugly. But.,

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

use vsoftco answer :)

0
source

Actually, this is not expected since iter really different from charMap.rbegin().base() .

Your logic is correct, the only problem is that the charMap.rbegin().base() charMap.end() is equal to charMap.end() , but you leave your for statement at the time iter reaches charMap.end() , so it never it was possible to check it in the if statement inside the for loop.

To do this, you can rewrite the if statement as follows:

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

So, you will compare the map key instead of the iterator itself.

0
source

It works:

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

Source: https://habr.com/ru/post/1235726/


All Articles