Я хотел бы создать случайную строку, состоящую из буквенно-цифровых символов. Я хочу, чтобы указать длину строки.
Как это сделать на С++?
Я хотел бы создать случайную строку, состоящую из буквенно-цифровых символов. Я хочу, чтобы указать длину строки.
Как это сделать на С++?
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;
}
Здесь моя адаптация Атеса Горала отвечает с использованием С++ 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
Зачем вам использовать С++ 11?
Например:
#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;
}
Мое решение 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;
}
 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;
 }
Я обычно использую структурированные пути С++ для такого рода инициализации. Обратите внимание, что в принципе это не отличается от решения Altan. Для программиста на С++ он просто выражает намерение немного лучше и может быть проще переноситься на другие типы данных. В этом случае функция С++ 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';
Кстати, прочитайте сочинение Джульенна о том, почему этот расчет индекса предпочтительнее более простых методов (например, взятия модуля).
Я только что протестировал это, он работает сладко и не требует таблицы поиска. 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;
}
Я надеюсь, что это поможет кому-то.
Протестировано при https://www.codechef.com/ide с С++ 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
Вот смешной однострочный. Требуется ASCII.
void gen_random(char *s, int l) {
    for (int c; c=rand()%62, *s++ = (c+"07="[(c+16)/26])*(l-->0););
}
Что-то еще более простое и более базовое, если вы довольны тем, что ваша строка содержит любые печатные символы:
#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
}
Случайная строка, каждый файл запуска = другая строка
        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);
Пример использования 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;
}
#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;
}
#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;
}
#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. 
 Вы можете легко добавить один заголовочный файл в свой проект, а затем добавить свои тесты. 
 Напишите ваши предложения по улучшению ниже.
https://gist.github.com/VjGusev/e6da2cb4d4b0b531c1d009cd1f8904ad
Я составил хорошее решение С++ 17 только для заголовков. Вы можете легко добавить один заголовочный файл в свой проект, а затем добавить свои тесты или использовать случайные строки для других целей.
Это краткое описание, но вы можете перейти по ссылке, чтобы проверить полный код. Основная часть решения находится в классе 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
Вот мое решение, которое я создал для тестирования алгоритмов сортировки. Он ограничен только буквенными символами, но вы можете развернуть его, чтобы включить числовые. Диапазон аргументов указывает генератору максимальную длину ваших строк; из-за характера моей реализации (я думал, что это так;)) вы получите строки с длиной в интервале [1; диапазон + 1] (см. size_t length).
Примечание.. Возможно, вы захотите рассмотреть возможность сброса C rand() и использования случайной библиотеки С++, поскольку во втором есть много генераторов, с которыми вы можете экспериментировать, а общий дистрибутив и диапазон намного лучше чем у rand() от cstdlib. Если вы используете rand(), не забудьте вызвать srand (SOME_SEED), прежде чем вы вызовете свой rand(). В противном случае вы получите те же "случайные" значения.: D
  std::string randstr(size_t range) {
    size_t length = rand() % range + 1;
    char str[length];
    str[length-1] = '\0';
    size_t i = 0;
    int r;
    for(i = 0; i < length-1; ++i) { //length-1 for the '\0' at the end
      for(;;) {
        r = rand() % 57 + 65; //interval between 65 ('A') and 65+57=122 ('z')
        if((r >= 65 && r <= 90) || (r >= 97 && r <= 122)) { // exclude all characters between '[' and '`'; you can add numerical characters here as an interval of ASCII code the same way I did that with the alphabetic characters
          str[i] = (char)r;
          break;
        }
      }
    }
    return std::string(str);
  }
Быть при вызове функции
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 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';
}