Jump to content
  • Advertisement
Sign in to follow this  
jden

"Automatic" fill

This topic is 2794 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,
Im testing the fill <algorithm> command.
I want to fill a vector of five elements with numbers 1 - 5.
I think a for loop could do this. But there is a problem:

vector<int> vec(5);
for(int f = 1; f < 5; ++f)
{
fill( vec.begin()+(--f), vec.end(), f );
}

As you can see I want to start at position 0, and with the val 1. Then it should
automatically assign each value every iteration.
Logically I think it would work, but instead it becomes an endless loop.
I know I could do one more value and it would work, but do you see any thinner solution or answer? Thanks!


Share this post


Link to post
Share on other sites
Advertisement
Think logically about what the '--f' is doing in that loop and you'll soon realise why it becomes an infinite loop.

I'm pretty sure you have a nice chunk of undefined behaviour there as well with the args to the 'fill' function; if memory serves the order parameters are evaluated aren't fixed, and I'm pretty sure the access/modification to 'f' is undefined as well (lack of sequence points).
(Someone correct me if I'm wrong here).

Share this post


Link to post
Share on other sites
When you fix that, be sure to change your loop condition either to f<=5 or f < 6. Otherwise you'll only get the numbers 1 -> 4.

Share this post


Link to post
Share on other sites
Quote:
Original post by Chris_F

vector<int> vec(5);
int f = 1;
for(auto it = vec.begin(); it != vec.end(); ++it)
{
*it = f++;
}


You can simplify it even more if you're going to use C++0x, by using initializer lists (assuming compiler support is there currently):


std::vector<int> vec = {1, 2, 3, 4, 5};

Share this post


Link to post
Share on other sites
From your answers I think I now know why it doesn't work, the for-loop is
a statement in which a formal parameter always increment it's own scope no matter if you try to use it just for positioning instructions only:

fill(vec.begin() + 0, vec.end(), 1)
->
fill(vec.begin() + 4, vec.end(), 5)
---------------------------------- =
fill(vec.begin() +(--f), vec.end(), f)

Besides your examples, this also works well :
fill(vec.begin()+f, vec.end(), f + 1)

But is it someway possible to make use of "icrementing / decrementing instructions" in iterative loops at all?

Share this post


Link to post
Share on other sites
Basically you are just trying to use an algorithm for something that it is not supposed for. Why use a O(n*n) algorithm for a O(n) operation?

There are many better ways, e.g using a counting_iterator from boost.


#include <vector>
#include <boost/iterator/counting_iterator.hpp>
#include <iostream>
#include <algorithm>
#include <iterator>

int main()
{
std::vector<int> vec(5);
std::copy(boost::make_counting_iterator(1), boost::make_counting_iterator(6), vec.begin());

std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
}

Share this post


Link to post
Share on other sites
I didn't understand what the OP problem is, sorry.

I just wanted to point out that this statement is undefined behavior:
fill( vec.begin()+(--f), vec.end(), f );


You are modifying f and using it in another part of the expression, without a sequence point in between.

Share this post


Link to post
Share on other sites
The purpose of std::fill is to assign the same value to many elements of a sequence.

What you are trying to do is assign a different value to each of several elements, following some rule. The natural choice of standard library algorithm for this is std::generate.

The example of std::generate given in this doc even solves your specific problem.

You can also use a "counting iterator" (via third-party tools, or rolling it yourself) as shown in visitor's code. The idea is that we have objects that obey the iterator interface while pretending to "iterate" over a virtual, not-actually-existing "container" of all the integers in order; then we use the standard library algorithm std::copy to copy from this virtual container into a real one in order to get a sequence of real elements.

The infinite loop in your code is caused by the fact that '--f' changes the value of f in addition to simply producing the value used in your calculation. This cancels out the '++f' in the for-loop clause, so each time through the loop, 'f' has the same value, and the loop-exit condition is never met.

EDIT: Except for the part where, as alvaro correctly points out, this actually invokes undefined behaviour, although all practical compilers would produce something that ends up in an infinite loop (it's just that the actual effects on the container might vary).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!