2

So i have been making a password generator but i cant split the characters in the char that i have made to store the characters for the password:

#include <iostream>
#include <cstdlib>
#include <string>
#include <random>
#include <ctime>

using namespace std;

int main()
{
    char letras[] = {"abcdefghijklmnopqrstuvwxyz"};
    string senha;
    int tamanho;
    int num;

    cout<<"escreve a quantidade de letrasdsa"<<endl;
    cin >> tamanho;

    srand(time(0));

    for (int i = 0; i < tamanho ; i++){


    }

    return 0;
}

Can you please help me complete the last part?

Bernardo
  • 33
  • 6
  • 1
    Seeding the RNG from `time(0)` is a terrible idea from a security point of view. So is using the stdlib `srand` and `rand` functions. – Thomas Jan 15 '20 at 14:42
  • 1
    Use random function – Build Succeeded Jan 15 '20 at 14:43
  • 1
    you are using `std::string` so why not also for `letras` ? Also the question is not quite clear. Why you cannot split characters? What does it mean to "split characters" ? Can you include example input and output in the question please? – 463035818_is_not_an_ai Jan 15 '20 at 14:47
  • 1
    What do you mean by splitting the characters? If you need a random letter from your array, you'd go like `letras[random_value % 26]`. I'd personally prefer to use a string, though, allowing you to use a proper dynamic size. In any case, you should get rid of that habit of having non english variable names. Also, you should really initialize your variables. – Aziuth Jan 15 '20 at 14:48
  • 1
    Do you know how to choose a random value between 0 and 25? If not, then write a very small `main` program to get familiar with how random number generator functions work and choosing a value between a range of integers. You seeded the random generator by using `srand()`, but nowhere do you do anything with `rand()` (let's forget that `rand()` is bad, but you get the point). – PaulMcKenzie Jan 15 '20 at 14:49

1 Answers1

8

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)]);
Evg
  • 25,259
  • 5
  • 41
  • 83
  • Where is the output in your demo? Ok, I spy it there. Well hidden, but futile! – Jaideep Shekhar Jan 15 '20 at 14:58
  • 1
    @JaideepShekhar, it should be at the bottom of the screen. – Evg Jan 15 '20 at 15:00
  • 1
    @JaideepShekhar "futile" ? Not sure but I think either me or you should look that word up in a dictionary again – 463035818_is_not_an_ai Jan 15 '20 at 15:03
  • @formerlyknownas_463035818 I had meant [this](https://english.stackexchange.com/a/352501). But yeah, I see it was perhaps not the best choice. – Jaideep Shekhar Jan 15 '20 at 15:13
  • @JaideepShekhar thats also what I understood. It appears a bit unkind to tell the answerer that the result is useless, because that is exactly the result OP was asking for. Nevermind, not my buisness ;) – 463035818_is_not_an_ai Jan 15 '20 at 15:14
  • @formerlyknownas_463035818 I believe you misunderstand. I referred to the _output_ of the demo, which was "hidden" from me, rather than to the answer. I am sorry for any misunderstanding. – Jaideep Shekhar Jan 15 '20 at 15:17
  • I mean, your code works and makes clever use of some STL functions, but wouldn't it be more effective to show the guy how to use random generators in general? Given that the guy did not manage to use the basic random functions, it is pretty clear that he is a beginner, right? – Aziuth Jan 16 '20 at 08:49
  • @Aziuth, I don't know what is the best strategy here. The question about using RNG in general has been answered multiple times already. – Evg Jan 16 '20 at 09:29
  • My compiler keeps saying that "sample" is not a member of "std" – Bernardo Jan 20 '20 at 13:32
  • @Bernardo Which compiler do you use and which version? `std::sample` requires C++17. – Evg Jan 20 '20 at 13:53
  • @Bernardo, I updated the answer with C++11 solution. – Evg Jan 20 '20 at 14:02
  • i just checked and i use c++11 , so it worked! Thank you. – Bernardo Jan 20 '20 at 14:47
  • But just a question here: is it possible to make the result change everytime i run the program? – Bernardo Jan 20 '20 at 14:57
  • @Bernardo, it looks like you're using [broken `random_device` implementation](https://stackoverflow.com/questions/18880654/why-do-i-get-the-same-sequence-for-every-run-with-stdrandom-device-with-mingw). Simplest (but not an ideal) solution: `std::mt19937 gen{static_cast(std::time(nullptr))};`. – Evg Jan 20 '20 at 15:10