我如何在c++中创建一个随机的字母数字字符串?

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

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

280600 次浏览
 void gen_random(char *s, size_t len) {
for (size_t i = 0; i < len; ++i) {
int randomChar = rand()%(26+26+10);
if (randomChar < 26)
s[i] = 'a' + randomChar;
else if (randomChar < 26+26)
s[i] = 'A' + randomChar - 26;
else
s[i] = '0' + randomChar - 26 - 26;
}
s[len] = 0;
}

Mehrdad Afshari的回答可以做到这一点,但我发现对于这个简单的任务来说,它有点太啰嗦了。查询表有时可以创造奇迹:

#include <ctime>
#include <iostream>
#include <unistd.h>


std::string gen_random(const int len) {
static const char alphanum[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
std::string tmp_s;
tmp_s.reserve(len);


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

return tmp_s;
}


int main(int argc, char *argv[]) {
srand((unsigned)time(NULL) * getpid());
std::cout << gen_random(12) << "\n";
return 0;
}

注意rand 生成质量差的随机数. c。

与其手动循环,不如使用适当的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)是真的很难。因此,上面的代码使用了一个helper函数模板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。通过添加所需的模板参数,可以对早期版本进行简单的修改。

我刚刚测试了这个,它工作得很好,不需要查找表。Rand_alnum()在某种程度上强制输出字母数字,但因为它从可能的256个字符中选择62个,所以这不是什么大问题。

#include <cstdlib>   // for rand()
#include <cctype>    // for isalnum()
#include <algorithm> // for back_inserter
#include <string>


char
rand_alnum()
{
char c;
while (!std::isalnum(c = static_cast<char>(std::rand())))
;
return c;
}




std::string
rand_alnum_str (std::string::size_type sz)
{
std::string s;
s.reserve  (sz);
generate_n (std::back_inserter(s), sz, rand_alnum);
return s;
}

我希望这能帮助到一些人。

用c++ 4.9.2在https://www.codechef.com/ide测试

#include <iostream>
#include <string>
#include <stdlib.h>     /* srand, rand */


using namespace std;


string RandomString(int len)
{
string str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
string newstr;
int pos;
while(newstr.size() != len) {
pos = ((rand() % (str.size() - 1)));
newstr += str.substr(pos,1);
}
return newstr;
}


int main()
{
srand(time(0));
string random_str = RandomString(100);
cout << "random_str : " << random_str << endl;
}
< p > <代码>输出: random_str: DNAT1LAmbJYO0GvVo4LGqYpNcyK3eZ6t0IN3dYpHtRfwheSYipoZOf04gK7OwFIwXg2BHsSBMB84rceaTTCtBC0uZ8JWPdVxKXBd

下面是我用c++ 11改编的Ates Goral的答案。我在这里添加了lambda,但原理是你可以传入它,从而控制你的字符串包含什么字符:

std::string random_string( size_t length )
{
auto randchar = []() -> char
{
const char charset[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
const size_t max_index = (sizeof(charset) - 1);
return charset[ rand() % max_index ];
};
std::string str(length,0);
std::generate_n( str.begin(), length, randchar );
return str;
}

下面是一个将lambda传递给随机字符串函数http://ideone.com/Ya8EKf的例子

为什么要使用c++ 11?

  1. 因为你可以为你感兴趣的字符集生成某个概率分布(或分布组合)后面的字符串。
  2. 因为它内置对非确定性随机数的支持
  3. 因为它支持unicode,所以你可以把它改成国际化的版本。

例如:

#include <iostream>
#include <vector>
#include <random>
#include <functional> //for std::function
#include <algorithm>  //for std::generate_n


typedef std::vector<char> char_array;


char_array charset()
{
//Change this to suit
return char_array(
{'0','1','2','3','4',
'5','6','7','8','9',
'A','B','C','D','E','F',
'G','H','I','J','K',
'L','M','N','O','P',
'Q','R','S','T','U',
'V','W','X','Y','Z',
'a','b','c','d','e','f',
'g','h','i','j','k',
'l','m','n','o','p',
'q','r','s','t','u',
'v','w','x','y','z'
});
};


// given a function that generates a random character,
// return a string of the requested length
std::string random_string( size_t length, std::function<char(void)> rand_char )
{
std::string str(length,0);
std::generate_n( str.begin(), length, rand_char );
return str;
}


int main()
{
//0) create the character set.
//   yes, you can use an array here,
//   but a function is cleaner and more flexible
const auto ch_set = charset();


//1) create a non-deterministic random number generator
std::default_random_engine rng(std::random_device{}());


//2) create a random number "shaper" that will give
//   us uniformly distributed indices into the character set
std::uniform_int_distribution<> dist(0, ch_set.size()-1);


//3) create a function that ties them together, to get:
//   a non-deterministic uniform distribution from the
//   character set of your choice.
auto randchar = [ ch_set,&dist,&rng ](){return ch_set[ dist(rng) ];};


//4) set the length of the string you want and profit!
auto length = 5;
std::cout<<random_string(length,randchar)<<std::endl;
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
}

我的2p解:

#include <random>
#include <string>


std::string random_string(std::string::size_type length)
{
static auto& chrs = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";


thread_local static std::mt19937 rg{std::random_device{}()};
thread_local static std::uniform_int_distribution<std::string::size_type> pick(0, sizeof(chrs) - 2);


std::string s;


s.reserve(length);


while(length--)
s += chrs[pick(rg)];


return s;
}
void strGetRandomAlphaNum(char *sStr, unsigned int iLen)
{
char Syms[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
unsigned int Ind = 0;
srand(time(NULL) + rand());
while(Ind < iLen)
{
sStr[Ind++] = Syms[rand()%62];
}
sStr[iLen] = '\0';
}

在调用函数时要小心

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羚改编)每次都会产生相同的字符序列。使用

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

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

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

Qt使用示例:

QString random_string(int length=32, QString allow_symbols=QString("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")) {
QString result;
qsrand(QTime::currentTime().msec());
for (int i = 0; i < length; ++i) {
result.append(allow_symbols.at(qrand() % (allow_symbols.length())));
}
return result;
}
#include <iostream>
#include <string>
#include <random>


std::string generateRandomId(size_t length = 0)
{
static const std::string allowed_chars {"123456789BCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz"};


static thread_local std::default_random_engine randomEngine(std::random_device{}());
static thread_local std::uniform_int_distribution<int> randomDistribution(0, allowed_chars.size() - 1);


std::string id(length ? length : 32, '\0');


for (std::string::value_type& c : id) {
c = allowed_chars[randomDistribution(randomEngine)];
}


return id;
}


int main()
{
std::cout << generateRandomId() << std::endl;
}
#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;
}

让我们再次让随机变得方便!

我做了一个漂亮的c++ 11头唯一的解决方案。 你可以很容易地将一个头文件添加到你的项目中,然后添加你的测试,或者为其他目的使用随机字符串

这是一个快速的描述,但是您可以通过链接查看完整的代码。解决方案的主要部分是在Randomer类中:

class Randomer {
// random seed by default
std::mt19937 gen_;
std::uniform_int_distribution<size_t> dist_;


public:
/* ... some convenience ctors ... */


Randomer(size_t min, size_t max, unsigned int seed = std::random_device{}())
: gen_{seed}, dist_{min, max} {
}


// if you want predictable numbers
void SetSeed(unsigned int seed) {
gen_.seed(seed);
}


size_t operator()() {
return dist_(gen_);
}
};

Randomer封装了所有随机的东西,你可以很容易地添加你自己的功能。有了Randomer之后,生成字符串就很容易了:

std::string GenerateString(size_t len) {
std::string str;
auto rand_char = [](){ return alphabet[randomer()]; };
std::generate_n(std::back_inserter(str), len, rand_char);
return str;
}
在下面写下你的改进建议。 https://gist.github.com/VjGusev/e6da2cb4d4b0b531c1d009cd1f8904ad < / p >

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

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

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

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

#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++ Simple Code
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<char> alphanum =
{'0','1','2','3','4',
'5','6','7','8','9',
'A','B','C','D','E','F',
'G','H','I','J','K',
'L','M','N','O','P',
'Q','R','S','T','U',
'V','W','X','Y','Z',
'a','b','c','d','e','f',
'g','h','i','j','k',
'l','m','n','o','p',
'q','r','s','t','u',
'v','w','x','y','z'
};
string s="";
int len=5;
srand(time(0));
for (int i = 0; i <len; i++) {
int t=alphanum.size()-1;
int idx=rand()%t;
s+= alphanum[idx];
}
cout<<s<<" ";
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)更改为另一个自定义值来调整可能生成的字符

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

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

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