如何在C ++中创建随机字母数字字符串?

时间:2009-01-13 18:16:30

标签: c++ string random

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

如何在C ++中执行此操作?

19 个答案:

答案 0 :(得分:256)

Mehrdad Afshari的answer会做到这一点,但我觉得这个简单的任务有点过于冗长。查找表有时可以创造奇迹:

void gen_random(char *s, const int len) {
    static const char alphanum[] =
        "0123456789"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz";

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

    s[len] = 0;
}

答案 1 :(得分:90)

这是我使用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,所以您可以将其更改为国际化版本。
  4. 例如:

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

    Sample output.

答案 2 :(得分:26)

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

答案 3 :(得分:15)

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

答案 4 :(得分:8)

我倾向于总是使用结构化的C ++方法进行这种初始化。请注意,从根本上说,它与Altan的解决方案没有什么不同。对于C ++程序员来说,它只是表达了更好的意图,并且可以更容易地移植到其他数据类型。在这个例子中,C ++函数generate_n完全表达了你想要的东西:

struct rnd_gen {
    rnd_gen(char const* range = "abcdefghijklmnopqrstuvwxyz0123456789")
        : range(range), len(std::strlen(range)) { }

    char operator ()() const {
        return range[static_cast<std::size_t>(std::rand() * (1.0 / (RAND_MAX + 1.0 )) * len)];
    }
private:
    char const* range;
    std::size_t len;
};

std::generate_n(s, len, rnd_gen());
s[len] = '\0';

顺便说一下,请阅读Julienne’s essay,了解为什么这个指数计算优于简单方法(如取模数)。

答案 5 :(得分:8)

我刚试过这个,它很好用,不需要查找表。 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;
}

答案 6 :(得分:7)

我希望这有助于某人。

使用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)
{
   srand(time(0));
   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()
{
   string random_str = RandomString(100);
   cout << "random_str : " << random_str << endl;
}

Output: random_str : DNAT1LAmbJYO0GvVo4LGqYpNcyK3eZ6t0IN3dYpHtRfwheSYipoZOf04gK7OwFIwXg2BHsSBMB84rceaTTCtBC0uZ8JWPdVxKXBd

答案 7 :(得分:3)

这是一个有趣的单行。需要ASCII。

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

答案 8 :(得分:2)

#include <random>
#include <iostream>

template<size_t N>
void genRandomString(char (&buffer)[N])
{
    std::random_device rd;  

    const char alphanumeric[] = {
        "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    };

    std::mt19937 eng(rd()); 
    std::uniform_int_distribution<> distr(0, 61); 

    for (auto& c : buffer)
        c = alphanumeric[distr(eng)];

    buffer[N] = '\0';
}

int main()
{
    char buffer[100]; // 99 is the string length
    genRandomString(buffer);

    std::cout << buffer << '\n';
    return 0;
}

答案 9 :(得分:1)

如果您对字符串包含任何可打印字符感到满意,那么更简单,更基本的东西:

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

答案 10 :(得分:1)

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

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

答案 11 :(得分:1)

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

答案 12 :(得分:1)

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

答案 13 :(得分: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;
}

答案 14 :(得分:0)

再进行一次改编,因为没有答案就可以满足我的需求。首先,如果使用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;
}

答案 15 :(得分:0)

Let's make random convenient again!

我组成了一个不错的C ++ 11 header only解决方案。 您可以轻松地将一个头文件添加到项目中,然后添加测试或将随机字符串用于其他用途。

这是一个简短的说明,但是您可以点击链接查看完整的代码。解决方案的主要部分是在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

答案 16 :(得分:0)

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

答案 17 :(得分:-1)

调用函数时要洁净

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

答案 18 :(得分:-2)

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