我想创建一个随机字符串,由字母-数字字符组成。我希望能够指定字符串的长度。
如何在c++中做到这一点?
我想创建一个随机字符串,由字母-数字字符组成。我希望能够指定字符串的长度。
如何在c++中做到这一点?
当前回答
//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;
}
其他回答
而不是手动循环,更喜欢使用适当的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。通过添加所需的模板参数,可以对早期版本进行简单的修改。
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生成的随机数质量很差。
标准库中最合适的函数是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;
}
}
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;
}