//3.14.7
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
#include <random>
#include <algorithm>
#include <array>
using std::string, std::vector, std::cout, std::endl, std::ostream_iterator, std::array, std::transform;
void LambdaTestFun_0( void )
{
vector< int > vec;
// Is it ok?
//auto rand = [] ( const int from = 1, const int to = 1000 ) { return (std::uniform_int_distribution<int>( from, to ) )( std::default_random_engine( (std::random_device())() ) ); };
//auto gen = bind(normal_distribution<double>{15,4.0},default_random_engine{}); // from Stroustrup
// Insert 10 random values to vec
generate_n( back_inserter( vec ), 10, std::rand ); // or use rand or gen from the previous lambda, after you uncomment them?
cout << "Here are all the " << vec.size() <<" random elements created and placed in the vector:"<< endl;
for(size_t i=0; i<vec.size(); ++i) cout << vec[i] << " ";
cout<<"\nFrom the above elements, the ones that are smaller than 1000 are: " <<endl; //maybe none will be <1000
// Print only if element less than 1000
copy_if( vec.begin(), vec.end(), ostream_iterator< int >( cout, "," ), [] ( auto x ) { return x < 1000; } );
cout << endl;
}
void LambdaTestFun_1( void )
{
// Fill array with odd values
const int k_elems = 10;
array< int, k_elems > odd_vals {}; // fill all with 0
// Fill odd_vals with odd values
char counter {};
transform( odd_vals.begin(), odd_vals.end(), odd_vals.begin(),
// Caption [& counter] used to pass counter by reference
// auto & is an empty placeholder for the argument passed by transform
[& counter]( auto & ){ return 2 * (counter++) + 1; }
);
cout << "\n An array with " << k_elems << " odd values:" << endl;
copy( odd_vals.begin(), odd_vals.end(), ostream_iterator< int >( cout, " " ) );
cout << endl;
}
void LambdaTestFun_2( void )
{
// Chars used to generate passwords, put them in 3 literal strings
const vector< string > rand_strings { "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz", "0123456789_@&#" };
std::srand( (unsigned int) time( 0 ) ); // seed random generator
// Generated value can be from 0 .. max_val-1. We could use default caption [=] to access RAND_MAX;
// However, a better way is to create a local copy rm via the "init capture" (generalized captures).
// -> int to explicitly convert return value from double to int
cout << RAND_MAX << " to be used" << endl;
auto rand_index = [ rm = RAND_MAX ] ( const int max_val ) //-> int
{
return static_cast<double>( std::rand() * max_val ) / static_cast<double>( rm + 1 ); // static_cast to make division on doubles
//return std::rand() * max_val % ( rm + 1 );
};
// Let's generate a few exemple passwords ...
const int kPswdToGenerate { 10 };
for( int cnt = kPswdToGenerate; cnt > 0; cnt-- )
{
string pwd;
// Insert kPasswordLen random chars via lambda function
const int kPasswordLen = 8;
generate_n ( back_inserter( pwd ), kPasswordLen,
// Use lambda which calls another lambda passed by reference. However, avoid default [&]
[ & rand_strings, & rand_index ] ()
{
const auto & s = rand_strings[ rand_index( rand_strings.size() ) ];
return s[ rand_index( s.size() ) ];
}
);
cout << "Proposed password: " << pwd << endl;
}
}
int main()
{
LambdaTestFun_0();
LambdaTestFun_1();
LambdaTestFun_2();
}
For LambdaTestFun_2() it is obvious that the generated random index is always 0, so always the 'A' is picked. I tried to fix it , but could not. I did various changes in the lambda auto rand_index but I was still getting all A , or for some changes I got segmentation fault.