1

In C++ I can use reverse_iterator to loop elements of container, say, list, backwards.

How do I iterate over a certain number of elements? Not reaching the beginning? This code works, but I feel there is a better way.

std::list<int> mylist{1,2,3,4,5};
int cnt = 3;
for (auto rit = mylist.rbegin(); rit != mylist.rend(); ++rit) {
    if (cnt == 0) break;
    std::cout << *rit << " ";
    --cnt;
}

Expected output {5, 4, 3}.

4

3 回答 3

4

You can adjust the loop as follows:

for (auto rit = mylist.rbegin(); rit != std::next(mylist.rbegin(), 3); ++rit)
{
   std::cout << *rit << " ";
}

but note that for this to work reliably, you need to check that the list is at least of size 3 or adjust the parameter to std::next as in const auto n = std::min<std::size_t>(3, mylist.size());.

With C++20, you should be able to go with (obviously not tested)

#include <ranges>

for (int n : mylist | std::ranges::reverse_view | std::ranges::take_view(3))
  std::cout << n << "\n";

This renders the size testing superfluous, as take_view is bound by the range size (it performs this check internally).

于 2019-06-06T09:53:32.623 回答
4

Not reaching the beginning?

If you can guarantee that, then

std::copy_n(mylist.rbegin(), 3, std::ostream_iterator<int>(std::cout, " "));

Or to be safer

std::copy_n(mylist.rbegin(), std::min(mylist.size(), std::list<int>::size_type(3)), std::ostream_iterator<int>(std::cout, " "));

LIVE

于 2019-06-06T09:55:19.653 回答
2

I would not put incrementing/decrementing and checking the condition in the loop body, but rather put it where you most expect it:

std::list<int> mylist{1,2,3,4,5};
int cnt = 3;
for (auto rit = mylist.rbegin(); rit != mylist.rend() && cnt > 0; ++rit,--cnt) {
    std::cout << *rit << " ";
}

Now you could for example add a continue anywhere in the loop body without making the loop go havoc.

PS: actually I like the other answers better, but I'll leave this one as it is minimal changes and imho incrementing / checking a loop counter inside the loop body is something to be avoided if possible (and it is possible here).

于 2019-06-06T09:54:57.280 回答