The C++ Standard Library provides several algorithms for assigning values to a range (such as a container or a C-array).

fill and fill_n

std::fill assigns a given value to all the elements in a range. It is available in the header <algorithm> . In the following example all elements of a vector of integers are assigned the value 1.

std::vector<int> data(10); std::fill(std::begin(data), std::end(data), 1); 1 2 std :: vector < int > data ( 10 ) ; std :: fill ( std :: begin ( data ) , std :: end ( data ) , 1 ) ;

std::fill_n is similar, but instead taking the bounds of a range it takes the beginning and a count and initializes N elements starting from the specified first element. You must make sure that first + count does not exceed the bounds of the range. The following example is an equivalent of the first:

std::vector<int> data(10); std::fill_n(std::begin(data), data.size(), 1); 1 2 std :: vector < int > data ( 10 ) ; std :: fill_n ( std :: begin ( data ) , data . size ( ) , 1 ) ;

generate and generate_n

These algorithms are similar to the first, but instead of taking a value to assign they take a function and assign the value returned by the function. They are also available in the header <algorithm> .

std::generate assigns the elements in a range the values returned by a function.

In the following example we initialize a vector of 10 elements with random numbers (using a Marsenne twister engine).

std::mt19937 rnd(static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count())); std::vector<int> data(10); std::generate(std::begin(data), std::end(data), rnd); for(auto const & d : data) { std::cout << d << std::endl; } 1 2 3 4 5 6 7 8 std :: mt19937 rnd ( static_cast < unsigned int > ( std :: chrono :: system_clock :: now ( ) . time_since_epoch ( ) . count ( ) ) ) ; std :: vector < int > data ( 10 ) ; std :: generate ( std :: begin ( data ) , std :: end ( data ) , rnd ) ; for ( auto const & d : data ) { std :: cout << d << std :: endl ; }

The result may look like this:

-630855823 -1828303634 473207879 1464137724 1046536659 1518951902 1516051318 -2076855687 -1620034611 -991968006 1 2 3 4 5 6 7 8 9 10 - 630855823 - 1828303634 473207879 1464137724 1046536659 1518951902 1516051318 - 2076855687 - 1620034611 - 991968006

You can use lambdas as the function whose return value is stored into the range. The following example generates random numbers ranging from 1 to 100 with a uniform distribution.

std::mt19937 rnd(static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count())); std::vector<int> data(10); std::uniform_int_distribution<> ud(1, 100); std::generate(std::begin(data), std::end(data), [&](){return ud(rnd);}); for(auto const & d : data) { std::cout << d << std::endl; } 1 2 3 4 5 6 7 8 9 std :: mt19937 rnd ( static_cast < unsigned int > ( std :: chrono :: system_clock :: now ( ) . time_since_epoch ( ) . count ( ) ) ) ; std :: vector < int > data ( 10 ) ; std :: uniform_int_distribution <> ud ( 1 , 100 ) ; std :: generate ( std :: begin ( data ) , std :: end ( data ) , [ & ] ( ) { return ud ( rnd ) ; } ) ; for ( auto const & d : data ) { std :: cout << d << std :: endl ; }

Result may look like this:

48 10 15 63 34 2 22 71 15 37 1 2 3 4 5 6 7 8 9 10 48 10 15 63 34 2 22 71 15 37

std::generate_n is similar, but instead of taking the limits of the range it takes the beginning and a count and assigns the first N values returned by the function to the range. You must makes sure that first + count does not exceeds the bounds of the range.

In the following example we initialize the elements of a vector with values from 1 to N, where N is the size of the range.

std::vector<int> data(10); int n = 1; std::generate_n(std::begin(data), data.size(), [&](){return n++;}); for(auto const & d : data) { std::cout << d << std::endl; } 1 2 3 4 5 6 7 8 std :: vector < int > data ( 10 ) ; int n = 1 ; std :: generate_n ( std :: begin ( data ) , data . size ( ) , [ & ] ( ) { return n ++ ; } ) ; for ( auto const & d : data ) { std :: cout << d << std :: endl ; }

The result is:

1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10

iota

std::iota is a new algorithm to C++11. It assigns the elements of a range with sequentially increasing values starting from a given value. The algorithm is available in header <numeric> .

The following example initializes the elements of a vector with values from 1 to N, where N is the size of the range (basically the same thing we did in the last example).

std::vector<int> data(10); std::iota(std::begin(data), std::end(data), 1); for(auto const & d : data) { std::cout << d << std::endl; } 1 2 3 4 5 6 7 std :: vector < int > data ( 10 ) ; std :: iota ( std :: begin ( data ) , std :: end ( data ) , 1 ) ; for ( auto const & d : data ) { std :: cout << d << std :: endl ; }

The result is:

1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10

Notice that the term iota is taken from the APL programming language and denotes the Greek letter ⍳ used in various mathematical notations.

Share this: Twitter

LinkedIn

StumbleUpon

Facebook

Reddit

More

Google

Email



Print

