If you want to generate a random password of length tamanho
out of these characters, use std::sample
algorithm:
const char letras[] = "abcdefghijklmnopqrstuvwxyz";
std::size_t tamanho = 10;
std::string senha;
senha.reserve(tamanho);
std::sample(std::begin(letras), std::end(letras) - 1, std::back_inserter(senha),
tamanho, std::mt19937{std::random_device{}()});
std::cout << senha; // Sample output: bdefjkmosx
1
is subtracted from std::end(letras)
, because string literals are zero-terminated, and we don't want to include the '\0'
character into the password. For const std::string letras = "...";
you don't need that subtraction.
Demo
Edit!
If you try to generate a password of 26 letters or more, you'll see that the previous solution is not correct. It does generate short random passwords, but
If n
is greater than the number of elements in the sequence, selects last-first
elements. The algorithm is stable (preserves the relative order of the selected elements) only if PopulationIterator
meets the requirements of LegacyForwardIterator
.
That is, it limits the password length and preserves the order of letters making it impossible to get a password like "z....a".
Possible fix is to ask std::sample
for 1 character tamanho
times:
std::string senha;
senha.reserve(tamanho);
std::mt19937 gen{std::random_device{}()};
std::generate_n(std::back_inserter(senha), tamanho, [&]() {
char ch;
std::sample(std::begin(letras), std::end(letras) - 1, &ch, 1, gen);
return ch;
});
Demo
or
std::string senha(tamanho, ' ');
std::mt19937 gen{std::random_device{}()};
for (auto& ch : senha)
std::sample(std::begin(letras), std::end(letras) - 1, &ch, 1, gen);
Demo
Edit 2.
If you don't have access to C++17 compiler, you can use std::uniform_int_distribution
to get C++11 solution:
std::string senha;
senha.reserve(tamanho);
std::mt19937 gen{std::random_device{}()};
std::uniform_int_distribution<std::size_t> d(0, std::end(letras) -
std::begin(letras) - 2);
for (std::size_t i = 0; i < tamanho; ++i)
senha.push_back(letras[d(gen)]);