快速随机串

Wiz*_*zix 1 c++ random qt c++11

我正在尝试为程序生成随机字符串ID(该ID必须在程序执行期间才是唯一的).我首先在Python中做到没有任何问题:

class RandomIdGenerator:
    _base_62_chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

    @classmethod
    def get_base_62(cls, length):
        return "".join([random.choice(RandomIdGenerator._base_62_chars) for _ in range(length)])
Run Code Online (Sandbox Code Playgroud)

但是因为我需要我的程序使用C++,所以我试图用它生成相同的字符串.这就是我现在所做的:

void Node::setId()
{
    QString allow_symbols("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
    qsrand(QTime::currentTime().msec());

    for (int i = 0; i < ID_LENGTH; ++i) {
        id_.append(allow_symbols.at(qrand() % (allow_symbols.length())));
    }
}
Run Code Online (Sandbox Code Playgroud)

我有两个主要问题.首先它不使用C++ 11(我不知道Qt是如何工作的,但我不认为它是C++ 11)并且生成的ID都是相同的.如果我生成其中四个我得到:

"R4NDM1xM"
"R4NDM1xM"
"R4NDM1xM"
"R4NDM1xM"
Run Code Online (Sandbox Code Playgroud)

我尝试使用C++ 11方法但是我得到了相同的结果,更糟糕的是,在每次执行时,我得到了完全相同的结果:

void Node::setId()
{
    id_ = "";

    const std::string str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

    std::random_device rd;
    std::mt19937 generator(rd());
    std::uniform_int_distribution<int> dist(0, str.size() - 1);

    for (int i = 0; i < Node::ID_LENGTH; ++i)
        id_ += str[dist(generator)];
}
Run Code Online (Sandbox Code Playgroud)

如何在每次调用方法时生成随机字符串ID?

Nat*_*ica 7

随机数生成器只应播种一次,除非您需要再次重复"ramdom"序列.这意味着qsrand(QTime::currentTime().msec());只应在您第一次进入时调用setId().这有点棘手,因为它是一个函数调用,但你可以添加一个静态bool变量来跟踪它是否已经运行,如果它已经不再调用它.就像是

void Node::setId()
{
    static bool seeded = false;
    QString allow_symbols("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
    if (!seeded) 
    {
        qsrand(QTime::currentTime().msec());
        seeded = true;
    }

    for (int i = 0; i < ID_LENGTH; ++i) {
        id_.append(allow_symbols.at(qrand() % (allow_symbols.length())));
    }
}
Run Code Online (Sandbox Code Playgroud)

C++ 11代码更容易.由于随机生成器是一个对象,因此您可以将其设置为静态,并且仅在第一次调用该函数时进行初始化.这意味着您的代码变为:

void Node::setId()
{
    id_ = "";
    id_.reserve(Node::ID_LENGTH); // preallocate storage

    static const std::string str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

    static std::random_device rd;
    static std::mt19937 generator(rd());
    static std::uniform_int_distribution<int> dist(0, str.size() - 1);

    for (int i = 0; i < Node::ID_LENGTH; ++i)
        id_ += str[dist(generator)];
}
Run Code Online (Sandbox Code Playgroud)

还应注意,std::random_device它由非确定性来源支持.如果您的实现不支持,那么std::random_device每次调用它时可能会生成相同的序列.如果是这种情况,那么您将不得不使用另一个选项来播种,generator如使用当前时间.