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

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


当前回答

#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;
}

其他回答

您可以使用random()方法生成一个基本的随机字符串。 下面的代码生成一个由小写字母、大写字母和数字组成的随机字符串。

String randomStrGen(int numChars){
  String genStr="";
  int sizeStr=0;
  
  while(sizeStr<numChars){
    int asciiPos= random(48,122);
    if((asciiPos>57 && asciiPos<65) || (asciiPos>90 && asciiPos<97))
      continue;
    genStr+=(char) asciiPos;
    sizeStr++;
  }
  
  return genStr;
}

如果需要更安全的随机数生成器,只需将random()函数替换为更安全的随机数生成器。

此外,还可以通过将ASCII限制(48,122)更改为另一个自定义值来调整可能生成的字符

这里有一个有趣的单句。需要ASCII。

void gen_random(char *s, int l) {
    for (int c; c=rand()%62, *s++ = (c+"07="[(c+16)/26])*(l-->0););
}

标准库中最合适的函数是std::sample:

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

static const char charset[] = 
    "0123456789"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz";

template<typename URBG>
std::string gen_string(std::size_t length, URBG&& g) {
    std::string result;
    result.resize(length);
    std::sample(std::cbegin(charset), 
                std::cend(charset),
                std::begin(result),
                std::intptr_t(length),
                std::forward<URBG>(g));
    return result;
}

int main() {
    std::mt19937 g;
    std::cout << gen_string(10, g) << std::endl;
    std::cout << gen_string(10, g) << std::endl;
}

随机数生成器的状态应该在调用之间保持在函数之外。

在调用函数时要小心

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;
    }
}

而不是手动循环,更喜欢使用适当的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。通过添加所需的模板参数,可以对早期版本进行简单的修改。