如何在同一个 srand() 种子中获得两个不同的随机数? C++

How do I get two different random numbers in the same srand() seed? C++

我正在尝试创建一个随机密码生成器。当我多次调用该函数时,它 returns 相同的字符值。 QQpQ;7Q7pQ;p

我已经尝试在我的主函数中添加 srand(time(0));srand((unsigned int) time(NULL));

查看其他 stack over flow 帖子时,我发现每次 运行 程序时 srand 都有助于创建不同的字符。但是它仍然是相同字符的 returns 倍数。

如何在 运行 时间内更改 srand() 种子以获得不同的随机数?

#include <string>
#include <iostream>
#include <time.h>

using namespace std;

string randomGenerator(int numberOfCharacters);
char randomCapitalCharacter();
char randomLowerCharacter();
char randomSpecialCharacter();
char randomInt();

int main(){
    srand((unsigned int) time(NULL));
    int passwordLength = 12;
    string password = randomGenerator(passwordLength);
    cout << password << endl;
    return 0;
}

string randomGenerator(int numberOfCharacters){
    char randomCharacterTypes[4] = {randomLowerCharacter(),randomInt(), randomCapitalCharacter(), randomSpecialCharacter()};
    std::string password;

    while (numberOfCharacters > 0){
        int random = rand()%4;
        password += randomCharacterTypes[random];
        numberOfCharacters--;
    }
    return password;
}
char randomInt(){
    std::string numberAsString = to_string(std::rand()% 10);
    char randomNumberChar = numberAsString.at(0);
    return randomNumberChar;
}
char randomLowerCharacter(){
    return 97 + rand()%26; //97 = a
}
char randomCapitalCharacter(){
    return 65 + rand()%26; //65 = A
}
char randomSpecialCharacter(){
    /** Special characters are split by numbers so we pick a random from one of the 2 groups.*/
    return (rand()%2) ? char(33 + rand()%14) : char(58 + rand()%8); 
}

感谢@RetiredNinja 指出问题不在于 srand(),而在于我的数组中的函数调用不当。使用 switch 语句调用函数正确解决了这个问题。

//improper calling of functions in an array. Resolved with switch statement below
//char randomCharacterTypes[4] = {randomLowerCharacter(),randomInt(), randomCapitalCharacter(), randomSpecialCharacter()};

while (numberOfCharacters > 0){
    int random = rand()%4;
    switch(random){
    case 0:
        password += randomLowerCharacter();
        break;
    case 1:
        password += randomInt();
        break;
    case 2:
        password += randomCapitalCharacter();
        break;
    case 3:
        password += randomSpecialCharacter();
        break;
    }
    numberOfCharacters--;
}

randomCharacterTypes 是一个包含 4 个字符的数组,对于每个字符 class,您将始终得到相同的字符。如果你想每次都生成一个新字符,你可以使用函数指针代替:

string randomGenerator(int numberOfCharacters){
    char (*randomCharacterTypes[])() = {randomLowerCharacter,randomInt, randomCapitalCharacter, randomSpecialCharacter};
    std::string password;

    while (numberOfCharacters > 0){
        int random = rand()%4;
        password += randomCharacterTypes[random]();
        numberOfCharacters--;
    }
    return password;
}

randomInt 可以简化为 return '0''9' 之间的字符,与您的其他函数相同:

char randomInt(){
    return '0' + rand() % 10;
}

如果您使用字符而不是数字,您的其他函数将更具可读性,然后您必须添加注释以提醒您它们代表哪个字符:

char randomLowerCharacter(){
    return 'a' + rand()%26;
}
char randomCapitalCharacter(){
    return 'A' + rand()%26;
}
char randomSpecialCharacter(){
    /** Special characters are split by numbers so we pick a random from one of the 2 groups.*/
    return (rand()%2) ? char('!' + rand()%14) : char(':' + rand()%8); 
}

请注意 不是一个好的随机数生成器,您应该改用标准库随机函数(特别是如果您将这些密码用于任何重要的事情)。

您的代码可能会进一步简化,使用 strings 来包含您的角色 classes:

#include <string>
#include <string_view>
#include <iostream>
#include <random>
#include <array>

class PasswordGenerator
{
public:
    PasswordGenerator()
    {
        for (size_t i = 0; i < characterTypes.size(); i++)
        {
            characterTypeDistributions[i] = std::uniform_int_distribution<int>(0, characterTypes[i].size() - 1);
        }
    }

    static constexpr std::array<std::string_view, 4> characterTypes = {
            "abcdefghijklmnopqrstuvwxyz",
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
            "0123456789",
            "!\"#$%&'()*+,-./:;<=>?@"
        };
    std::array<std::uniform_int_distribution<int>, characterTypes.size()> characterTypeDistributions;
    std::uniform_int_distribution<int> typeDistribution{0, characterTypes.size() - 1};
    std::mt19937 eng{std::random_device{}()};

    std::string generate(int numberOfCharacters){
        std::uniform_int_distribution<int> dist{0, 5};
        std::string password;
        password.reserve(numberOfCharacters);
        for (int i = 0; i < numberOfCharacters; i++)
        {
            auto type = typeDistribution(eng);
            password += characterTypes[type][characterTypeDistributions[type](eng)];
        }
        return password;
    }
};

int main(){
    int passwordLength = 12;
    PasswordGenerator gen;
    std::string password = gen.generate(passwordLength);
    std::cout << password << "\n";
    return 0;
}

请注意,此代码可能仍不符合生成密码的高安全标准。