我想创建一个随机字符串,由字母-数字字符组成。我希望能够指定字符串的长度。

如何在c++中做到这一点?


当前回答

在调用函数时要小心

string gen_random(const int len) {
static const char alphanum[] = "0123456789"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

stringstream ss;

for (int i = 0; i < len; ++i) {
    ss << alphanum[rand() % (sizeof(alphanum) - 1)];
}
return ss.str();
}

(改编自@Ates Goral)每次都会产生相同的字符序列。使用

srand(time(NULL));

在调用函数之前,rand()函数总是以1 @kjfletch作为种子。

例如:

void SerialNumberGenerator() {

    srand(time(NULL));
    for (int i = 0; i < 5; i++) {
        cout << gen_random(10) << endl;
    }
}

其他回答

随机字符串,每个运行文件=不同的字符串

        auto randchar = []() -> char
    {
        const char charset[] =
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            "abcdefghijklmnopqrstuvwxyz";

        const size_t max_index = (sizeof(charset) - 1);

        return charset[randomGenerator(0, max_index)];
    };
            std::string custom_string;
            size_t LENGTH_NAME = 6 // length of name
    generate_n(custom_string.begin(), LENGTH_NAME, randchar);

这是另一种改编,因为没有一个答案能满足我的需求。

首先,如果rand()用于生成随机数,那么每次运行都将得到相同的输出。随机数生成器的种子必须是某种随机的。

在c++ 11中,你可以包含随机库,并且可以使用random_device和mt19937初始化种子。这个种子将由操作系统提供,它对我们来说足够随机(例如,时钟)。你可以给出一个范围边界(在我的例子中是[0,25])。

我只需要随机字符串小写字母,所以我利用字符加法。“人物池”的方法并不适合我。

#include <random>    
void gen_random(char *s, const int len){
    static std::random_device rd;
    static std::mt19937 mt(rd());
    static std::uniform_int_distribution<int> dist(0, 25);
    for (int i = 0; i < len; ++i) {
        s[i] = 'a' + dist(mt);
    }
    s[len] = 0;
}

而不是手动循环,更喜欢使用适当的c++算法,在这种情况下std::generate_n,具有适当的随机数生成器:

auto generate_random_alphanumeric_string(std::size_t len) -> std::string {
    static constexpr auto chars =
        "0123456789"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz";
    thread_local auto rng = random_generator<>();
    auto dist = std::uniform_int_distribution{{}, std::strlen(chars) - 1};
    auto result = std::string(len, '\0');
    std::generate_n(begin(result), len, [&]() { return chars[dist(rng)]; });
    return result;
}

这接近于我所说的这个问题的“规范”解决方案。

不幸的是,正确地播种一个通用的c++随机数生成器(例如MT19937)是非常困难的。因此上面的代码使用了一个辅助函数模板random_generator:

template <typename T = std::mt19937>
auto random_generator() -> T {
    auto constexpr seed_bytes = sizeof(typename T::result_type) * T::state_size;
    auto constexpr seed_len = seed_bytes / sizeof(std::seed_seq::result_type);
    auto seed = std::array<std::seed_seq::result_type, seed_len>();
    auto dev = std::random_device();
    std::generate_n(begin(seed), seed_len, std::ref(dev));
    auto seed_seq = std::seed_seq(begin(seed), end(seed));
    return T{seed_seq};
}

这很复杂,而且效率相对较低。幸运的是,它用于初始化thread_local变量,因此每个线程只调用一次。

最后,上述的必要包括:

#include <algorithm>
#include <array>
#include <cstring>
#include <functional>
#include <random>
#include <string>

上面的代码使用类模板参数演绎,因此需要c++ 17。通过添加所需的模板参数,可以对早期版本进行简单的修改。

#include <iostream>
#include <string>
#include <stdlib.h>
int main()
{
    int size;
    std::cout << "Enter size : ";
    std::cin >> size;
    std::string str;
    for (int i = 0; i < size; i++)
    {
        auto d = rand() % 26 + 'a';
        str.push_back(d);
    }
    for (int i = 0; i < size; i++)
    {
        std::cout << str[i] << '\t';
    }

    return 0;
}

一些更简单和更基本的东西,如果你想让你的字符串包含任何可打印的字符:

#include <time.h>   // we'll use time for the seed
#include <string.h> // this is for strcpy

void randomString(int size, char* output) // pass the destination size and the destination itself
{
    srand(time(NULL)); // seed with time

    char src[size];
    size = rand() % size; // this randomises the size (optional)

    src[size] = '\0'; // start with the end of the string...

    // ...and work your way backwards
    while(--size > -1)
        src[size] = (rand() % 94) + 32; // generate a string ranging from the space character to ~ (tilde)

    strcpy(output, src); // store the random string
}