简体   繁体   中英

How do i find empty space in array and fill it with part of code / how do i rand 3 randed arrays into one and shuffle it randomly?

Got a task to do password generator.

Right now i have a problem with the output because if i build the code

here is the outcome.

so my problem is that i need to get something more like this with my own input choice and to mix it into each other so it wouldn't go like the first picture.

i hopefully made myself more clear about my problem.

i - stands for the number for cycle.

la - stands for the lower alphabet for cycle.

ha - stands for the higher alphabet for cycle.

#include <iostream>
#include<ctime>
using namespace std;
const char num[] = "0123456789";
const char lower_alp[] = "abcdefghijklmnopqrstuvwxyz";
const char higher_alp[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int sizeofnum = sizeof(num) - 1;
int sizeoflower_alp = sizeof(lower_alp) - 1;
int sizeofhigher_alp = sizeof(higher_alp) - 1;

int main()
{
   int password_length = 0, nums, loweralp, higheralp;
   cout << "Enter password length: ";
   cin >> password_length;
   cout << "How many lower alphabet symbols do you want in the password:";
   cin >> loweralp;
   cout << "How many higher alphabet symbols do you want in the password:";
   cin >> higheralp;
   cout << "How many numbers do you want in the password:";
   cin >> nums;
   srand(time(NULL));
       for (int i = 0; i < nums; i++) {
        cout << num[rand() % sizeofnum];
    }
    for (char la = 0; la < loweralp; la++) {
        cout << lower_alp[rand() % sizeoflower_alp];
    }
    for (char ha = 0; ha < higheralp; ha++) {
        cout << higher_alp[rand() % sizeofhigher_alp];
    }
     
    
    
    return 0;
}

using a std::string to store the characters You can randomly sort it using a function string_shuffle that will do the job.

void string_shuffle(std::string& str)
{
    auto rd = std::random_device{};
    auto rng = std::default_random_engine{ rd() };
    std::shuffle(str.begin(), str.end(), rng);
}

Tested using c++17

Don't write using namespace std; .

You can, however, in a CPP file (not H file) or inside a function put individual using std::string; etc. (See SF.7 .)


use constexpr for constants that are known at compile time.


None of these are necessary:

int sizeofnum = sizeof(num) - 1;
int sizeoflower_alp = sizeof(lower_alp) - 1;
int sizeofhigher_alp = sizeof(higher_alp) - 1;

and if you did need them, use size_t , make them constexpr , and generally don't use sizeof to determine collection sizes.


Don't repeat yourself.

You have three different lists, and duplicate the exact code for picking characters from them. Make it a general function that takes parameters.

This is the first step: choose n random characters from a list. The function can be declared like this:
string choose_n_rand (string_view choices, size_t n)
and the implementation should use uniform_int_distribution , not the nasty legacy rand function.


Call the three parts, and combine them into one string. The code would look something like this:

string pw = choose_n_rand (num, nums);
pw += choose_n_rand (lower_alpha, lower_alphas);
pw += choose_n_rand (upper_alpha, upper_alphas);

and then shuffle the resulting string, by calling shuffle from the standard library. To do that, you need to know about the random number library as that's one of the parameters. Look at the examples on Cppreference .

You want

std::random_device rd;
std::mt19937 gen{rd()};

as global variables at the top of the file, so that choose_n_rand can make use of the same gen .

To follow on the code above, the line would be:

std::ranges::shuffle (pw,gen);

Note that the example on the linked web page uses an array; but it works with any kind of collection so here we're passing a std::string .

recap

To answer your questions,

  1. You don't find empty space in an array to make your results. Rather, you use a container that can grow as you add things to it.

  2. You can combine three separate result strings into one easily by using operations on the std::string class. Above, I used += . There are many possibilities. Point is, these operations exist as part of the container classes, and you don't need to figure it out from scratch on a primitive array!

  3. To shuffle, call shuffle . know what's in the standard library .

If I understand you want to combine a random selection of characters from each of the 3 sets in a random order, then a convenient way to ensure you end up with a randomized selection from each set combined in a random order would be to:

  • shuffle each set initially,
  • create a string concatenating the needed number of characters from each shuffled string, and
  • shuffle the concatenated string.

You can build in that direction based upon the shuffle_string() answer received to do:

void shuffle_from_sets(std::string& str, size_t n1, size_t n2, size_t n3)
{
    std::random_device rd;
    std::mt19937 g(rd());
    
    std::string s1 {"abcdefghijklmnopqrstuvwxyz"},
                s2 {"ABCDEFGHIJKLMNOPQRSTUVWXYZ"},
                s3 {"0123456789"};
    
    std::shuffle (s1.begin(), s1.end(), g);     /* shuffle sets */
    std::shuffle (s2.begin(), s2.end(), g);
    std::shuffle (s3.begin(), s3.end(), g);
    
    /* create string from shuffled sets */
    str = s1.substr (0, n1) + s2.substr (0, n2) + s3.substr (0, n3);
        
    std::shuffle(str.begin(), str.end(), g);    /* shuffle final string */
}

( note: you would want to validate that n1 , n2 , n3 are less than or equal to the length of the set each draws from -- that if left to you)

You can also add a set with special characters to strengthen your final password, eg std::string s4 {"~!@#$%^&*()_+-={}|[]\\\\:\\";'<>?,./"};

A complete example would be:

#include <iostream>
#include <string>
#include <random>
#include <algorithm>

void shuffle_from_sets(std::string& str, size_t n1, size_t n2, size_t n3)
{
    std::random_device rd;
    std::mt19937 g(rd());
    
    std::string s1 {"abcdefghijklmnopqrstuvwxyz"},
                s2 {"ABCDEFGHIJKLMNOPQRSTUVWXYZ"},
                s3 {"0123456789"};
    
    std::shuffle (s1.begin(), s1.end(), g);     /* shuffle sets */
    std::shuffle (s2.begin(), s2.end(), g);
    std::shuffle (s3.begin(), s3.end(), g);
    
    /* create string from shuffled sets */
    str = s1.substr (0, n1) + s2.substr (0, n2) + s3.substr (0, n3);
        
    std::shuffle(str.begin(), str.end(), g);    /* shuffle final string */
}

int main (void) {
    
    std::string s{};
    size_t n1, n2, n3;
    
    std::cout << "no chars [a-z]  : ";
    if (!(std::cin >> n1)) {
        return 1;
    }
    std::cout << "no chars [A-Z]  : ";
    if (!(std::cin >> n2)) {
        return 1;
    }
    std::cout << "no chars [0-9]  : ";
    if (!(std::cin >> n3)) {
        return 1;
    }
    
    shuffle_from_sets (s, n1, n2, n3);
    
    std::cout << "shuffled string : " << s << '\n';
}

Example Use/Output

Building your randomized passwords from the sets would look similar to:

$ ./bin/string_shuffle_sets
no chars [a-z]  : 6
no chars [A-Z]  : 4
no chars [0-9]  : 3
shuffled string : LtW9bu53ksxIC

or

$ ./bin/string_shuffle_sets
no chars [a-z]  : 6
no chars [A-Z]  : 4
no chars [0-9]  : 3
shuffled string : yJKqP5hnbi3Q6

Look things over and let me know if you have further questions.

You could just save the desired characters into a string and then pick from that randomly. Doing that your code should look like this:

#include <iostream>
#include <ctime>
using namespace std;
const char num[] = "0123456789";
const char lower_alp[] = "abcdefghijklmnopqrstuvwxyz";
const char higher_alp[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int sizeofnum = sizeof( num ) - 1;
int sizeoflower_alp = sizeof( lower_alp ) - 1;
int sizeofhigher_alp = sizeof( higher_alp ) - 1;

int main()
{
    int password_length = 0, nums, loweralp, higheralp;
    cout << "Enter password length: ";
    cin >> password_length;
    cout << "How many lower alphabet symbols do you want in the password:";
    cin >> loweralp;
    cout << "How many higher alphabet symbols do you want in the password:";
    cin >> higheralp;
    cout << "How many numbers do you want in the password:";
    cin >> nums;
    srand( time( NULL ) );
    string possibleCharacters = "";
    string password = "";
    for( int i = 0; i < nums; i++ )
    {
        possibleCharacters += num[rand() % sizeofnum];
    }
    for( char la = 0; la < loweralp; la++ )
    {
        possibleCharacters += lower_alp[rand() % sizeoflower_alp];
    }
    for( char ha = 0; ha < higheralp; ha++ )
    {
        possibleCharacters += higher_alp[rand() % sizeofhigher_alp];
    }

    for( int i = 0; i < password_length; i++ )
    {
        int nextCharacterIndex = 0;
        if( i != 0 )
        {
            nextCharacterIndex = rand() % ( possibleCharacters.length() );
        }     
        password += possibleCharacters[nextCharacterIndex];
        possibleCharacters.erase( possibleCharacters.begin() + nextCharacterIndex );
    }
    cout << password;
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM