it-swarm.com.ru

Как создать случайную буквенно-цифровую строку в C++?

Я хотел бы создать случайную строку, состоящую из буквенно-цифровых символов. Я хочу, чтобы можно было указать длину строки.

Как мне сделать это в C++?

150
jm.

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;
}
252
Ates Goral

Вот моя адаптация ответа Ates Goral с использованием C++ 11. Я добавил здесь лямбду, но принцип в том, что вы можете передать ее и тем самым контролировать, какие символы содержит ваша строка:

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

Вот пример передачи лямбда-функции в случайную строку: 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;
}

Пример вывода.

89
Carl

Мое 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;
}
26
Galik
 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;
 }
15
Mehrdad Afshari

Я только что проверил это, он работает хорошо и не требует таблицы поиска. Rand_alnum () сортирует буквенно-цифровые символы, но поскольку он выбирает 62 из 256 возможных символов, это не имеет большого значения.

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

Я склонен всегда использовать структурированные способы C++ для такого рода инициализации. Обратите внимание, что в принципе, это не отличается от решения Алтана. Для программиста на 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';

Кстати, прочитайте эссе Жюльена о том, почему такое вычисление индекса предпочтительнее простых методов (таких как взятие модуля).

8
Konrad Rudolph

Я надеюсь, что это помогает кому-то.

Протестировано на https://www.codechef.com/ide с 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
D D

Вот забавная строчка. Нуждается в ASCII.

void gen_random(char *s, int l) {
    for (int c; c=Rand()%62, *s++ = (c+"07="[(c+16)/26])*(l-->0););
}
3
geza
#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;
}
2
Hazey

Пример использования 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
Vitalja Alex

Случайная строка, каждый прогон файла = другая строка

        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
Nehigienix
#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;
}
1
Oleg

Что-то еще более простое и более простое на случай, если вы довольны тем, что ваша строка содержит печатные символы:

#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
Nobilis
#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;
}
0
ras

Давайте сделаем случайным удобно снова!

Я составил решение для заголовка Nice 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

0
Gusev Slava