Jak utworzyć losowy ciąg alfanumeryczny w C++?

Chciałbym utworzyć losowy ciąg znaków, składający się ze znaków alfanumerycznych. Chcę być w stanie określić długość łańcucha.

Jak to zrobić w C++?

Author: jm., 2009-01-13

15 answers

ODPOWIEDŹ Mehrdada Afshariego załatwiłaby sprawę, ale uznałem ją za zbyt gadatliwą na to proste zadanie. Wyszukane tabele mogą czasem zdziałać cuda:

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;
}
 239
Author: Ates Goral,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:30

Oto moja adaptacja odpowiedzi Atesa Gorala za pomocą C++11. Dodałem tutaj lambdę, ale zasada jest taka, że możesz ją przekazać i tym samym kontrolować, jakie znaki Zawiera Twój ciąg znaków:

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

Oto przykład przejścia w lambdzie do funkcji losowego ciągu: http://ideone.com/Ya8EKf

Dlaczego używasz C++11 ?

  1. ponieważ można wytworzyć ciągi, które następują po pewnym rozkładzie prawdopodobieństwa (lub kombinacja dystrybucji) dla interesującego cię zestawu znaków.
  2. ponieważ posiada wbudowaną obsługę niedeterministycznych liczb losowych
  3. ponieważ obsługuje unicode, więc możesz to zmienić na wersję umiędzynarodowioną.

Na przykład:

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

Przykładowe wyjście.

 82
Author: Carl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-24 20:17:09

Moje rozwiązanie 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;
}
 25
Author: Galik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-16 14:16:06
 void gen_random(char *s, const int len) {
     for (int 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;
 }
 15
Author: Mehrdad Afshari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-13 18:20:26

Zazwyczaj zawsze używam ustrukturyzowanych sposobów C++ do tego rodzaju inicjalizacji. Zauważ, że zasadniczo nie różni się od rozwiązania Altana. Dla programisty C++, to po prostu wyraża zamiar nieco lepiej i może być łatwiejsze przenośne do innych typów danych. W tym przypadku funkcja C++ generate_n wyraża dokładnie to, co chcesz:

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

Przy okazji, przeczytaj esej Julienne o tym, dlaczego to obliczanie indeksu jest preferowane niż prostsze metody (jak biorąc moduł).

 8
Author: Konrad Rudolph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-14 20:53:37

Właśnie to przetestowałem, działa słodko i nie wymaga tabeli wyszukiwania. rand_alnum() wymusza alfanumerykę, ale ponieważ wybiera 62 z możliwych 256 znaków, nie jest to wielka sprawa.

#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;
}
 8
Author: nly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-17 12:06:20

Mam nadzieję, że to komuś pomoże.

Testowane w https://www.codechef.com/ide with C++ 4.9.2

#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
Author: thewall7,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-01 00:02:39

Tu jest zabawna jedna linijka. Potrzebuje ASCII.

void gen_random(char *s, int l) {
    for (int c; c=rand()%62, *s++ = (c+"07="[(c+16)/26])*(l-->0););
}
 2
Author: geza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-22 10:30:57

Coś jeszcze prostszego i bardziej podstawowego w przypadku, gdy jesteś szczęśliwy, że Twój ciąg zawiera dowolne drukowalne znaki:

#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
}
 1
Author: Nobilis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-22 13:28:16

Losowy ciąg znaków, każdy plik uruchomieniowy = inny ciąg znaków

        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);
 1
Author: Nehigienix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-01 11:58:58

Przykład użycia 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;
}
 1
Author: Vitalja Alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-08 10:09:02
#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;
}
 1
Author: Hazey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-07 13:43:39
#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;
}
 0
Author: Oleg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-22 09:39:24

Być ware podczas wywoływania funkcji

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

(zaadaptowane z @Ates Goral ) spowoduje to za każdym razem ten sam ciąg znaków. Użycie

srand(time(NULL));

Przed wywołaniem funkcji, chociaż funkcja rand () jest zawsze ustawiona na 1 @kjfletch .

Na Przykład:

void SerialNumberGenerator() {

    srand(time(NULL));
    for (int i = 0; i < 5; i++) {
        cout << gen_random(10) << endl;
    }
}
 -1
Author: Mr.Sheep,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:03
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';
}
 -2
Author: Деян Добромиров,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-03 07:32:02