我想创建一个随机字符串,由字母-数字字符组成。我希望能够指定字符串的长度。
如何在c++中做到这一点?
我想创建一个随机字符串,由字母-数字字符组成。我希望能够指定字符串的长度。
如何在c++中做到这一点?
当前回答
我的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;
}
其他回答
我刚刚测试了这个,它工作得很好,不需要查找表。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;
}
一些更简单和更基本的东西,如果你想让你的字符串包含任何可打印的字符:
#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
}
#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;
}
而不是手动循环,更喜欢使用适当的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生成的随机数质量很差。