214

I'd like to create a random string, consisting of alpha-numeric characters. I want to be able to be specify the length of the string.

How do I do this in C++?

jm.
  • 23,422
  • 22
  • 79
  • 93

20 Answers20

349

Mehrdad Afshari's answer would do the trick, but I found it a bit too verbose for this simple task. Look-up tables can sometimes do wonders:

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

Note that rand generates poor-quality random numbers.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
Ates Goral
  • 137,716
  • 26
  • 137
  • 190
  • 1
    Nice. I wanted to mention this in a comment. This approach works better if, like this example, the count of elements is small. The drawback is it doesn't scale well if you wanted to generate random numbers from large distinct continues sets. – Mehrdad Afshari Jan 13 '09 at 18:44
  • 1
    I like this answer better. It's more flexible, because you can eliminate characters easily. For example, making a random alphanumeric string without the character I would be trivial in this function. It is also easier to understand, in my opinion. – William Brendel Jan 13 '09 at 18:48
  • 1
    +1, This way you can add certain special char without having to worry about the entire set. Much better. – WolfmanDragon Jan 13 '09 at 18:49
  • Mehrdad, why does it not scale? an array of char is an array of char wherever it is digits or alphabet. This is not creating random ints or floats but chars. – WolfmanDragon Jan 13 '09 at 18:54
  • I said it doesn't scale "if...". Clearly, this is a good solution for these situations. – Mehrdad Afshari Jan 13 '09 at 18:56
  • We had a bit of a language barrier here on this one. "Thus, a continuous set is a conditionally-complete lattice which is a dense total order. The phrase "continuous set" is not used in the Western literature." from http://eom.springer.de/c/c025760.htm – WolfmanDragon Jan 13 '09 at 19:06
  • WolframDragon, sorry, English is not my native language. – Mehrdad Afshari Jan 13 '09 at 19:19
  • 1
    Your answer is a good approach, but you should remove the "- 1" from your algorithm. It is incorrect. It is easy to see this if you visualize a smaller array size, such as 1 or 2. – Drew Dormann Jan 13 '09 at 19:23
  • @Shmoopty - Thanks for the pointer. I already had my doubts when writing that but my VS was acting up and so I couldn't test my code :) – Ates Goral Jan 13 '09 at 20:24
  • 1
    Don't forget to call seed the random number generator :) – jm. Jan 13 '09 at 21:58
  • 1
    Don't forget to use a High Entropy source for your seed either. ( Ie: not 0 + process ID, I hear a slice of uninitialised memory works nice ) – Kent Fredric Jan 13 '09 at 22:31
  • this is a nice solution, +1 . but i think you want to index with "rand() % (sizeof(alphanum) - 1)", because the sizeof takes the terminating null character into account – Johannes Schaub - litb Jan 14 '09 at 04:12
  • 1
    ah, i just see you already had it in originally. well, it was right. let's see with an array of size 2: "1" ('1','\0'). (rand() % sizeof(alphanum)) would give you indices from 0..1 . but that is wrong, of course. – Johannes Schaub - litb Jan 14 '09 at 04:18
  • @litb - I knew it! I knew my gut feeling was right the first time. Reverted to use -1. Thanks! – Ates Goral Jan 14 '09 at 05:11
  • 8
    @Kent: that's what the OpenSSL team though, until someone thought of putting their code through valgrind. ;-) – Konrad Rudolph Jan 14 '09 at 20:58
  • 12
    You probably don't want to use a simple rand() with modulus. See: http://c-faq.com/lib/randrange.html – Randy Proctor May 15 '09 at 13:02
  • One downside to this approach that I should mention is, long tables/strings like this are a code review nightmare and are prone to stupid mistakes. – Ates Goral Aug 11 '11 at 14:21
  • 5
    I think the line `s[len] = 0` is incorrect. If `s` is a C string (NULL terminated) then the signature of the method would not have to have the `len`parameter in it. Imo, if you are passing the length as an argument, you are assuming the array is not a C string. Thus, if you are not passing a C string to the function, the line `s[len] = 0` could break things, since the array would go from 0 to len-1. And even if you are passing a C string to the function the line `s[len] = 0` would be redundant. – Fauth Oct 22 '12 at 19:04
  • 2
    This code could be dangerous, because typically functions with parameters like "len" include the terminating NULL in their count. But this function actually writes len+1 characters to the output string. So you would have to be careful using it, in that if you have `char buffer[16];` you actually call `gen_random(buffer, sizeof(buffer) - 1);` paying special attention to remembering the `- 1` – Malvineous Jun 17 '13 at 23:48
  • 1
    This will not work properly if you are using wide characters (i.e. wchar_t). sizeof() does not give you the number of items in an array, it gives you the number of bytes occupied. This will obviously be incorrect when using wide characters. You need to divide by sizeof(alphanum[0]) - or better yet, if using Visual Studio use [_countof](http://msdn.microsoft.com/en-us/library/ms175773%28v=vs.120%29.aspx) – jrupe Jan 09 '15 at 22:15
  • Can we make it `size_t len` and `size_t i`? :-) – Ciro Santilli OurBigBook.com Jun 27 '15 at 12:50
  • 29
    Please use C++11 or boost random, we're in 2016 now – Nikko Jan 29 '16 at 13:23
  • 1
    Its a copy paste from official c++ website. http://www.cplusplus.com/forum/windows/88843/ – BTR Naidu Mar 08 '17 at 10:32
  • @BTRNaidu Hi. Look at the dates. – Ates Goral Mar 08 '17 at 17:51
  • @AtesGoral apologies. I take my comment back. – BTR Naidu Mar 09 '17 at 09:40
  • 27
    We need a way to sink obsolete answers on stackoverflow. – Velkan May 23 '17 at 06:20
  • 1
    `rand()` ?!?!?! in 2018 !??! – Gusev Slava Dec 18 '18 at 16:10
  • 1
    @Velkan Answers can be updated, feel free to do so (but if you do, make sure that you mention in your edit comment that you're updating the answer for modern C++). – AStopher Feb 27 '19 at 00:51
  • @AtesGoral, Sometimes it is generating the same random number again. How to solve that? code shared below as answer. – Anjali Jul 20 '20 at 17:35
  • Using modern c++ and Using Mersene Twister 19937 generator and Uniform discrete distribution https://stackoverflow.com/a/50556436/6219626 – Haseeb Mir Jul 21 '20 at 03:00
  • 4
    I don't understand why people are getting furious about rand() usage. The question nowhere suggests the requirement of a well-distributed generator. Complicating simple stuff unnecessarily is a waste of time/energy for readers! – Jainam MJ Sep 25 '20 at 11:03
  • @JainamMJ the post should at least mention that `rand` is basically garbage to avoid misuse. I wouldn't say people are "getting furious" as much as calling attention to potentially dangerous code. Beyond that, this is a shoddy usage of `srand`. It's called inside the function using the time, so tight loops will result in a bunch of runs of the exact same number. I fixed these issues since it's a community wiki but it's still worth downvoting so we can move forward with better answers [like this one](https://stackoverflow.com/a/444614/6243352). – ggorlen Oct 26 '21 at 21:23
121

Here's my adaptation of Ates Goral's answer using C++11. I've added the lambda in here, but the principle is that you could pass it in and thereby control what characters your string contains:

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

Here is an example of passing in a lambda to the random string function: http://ideone.com/Ya8EKf

Why would you use C++11?

  1. Because you can produce strings that follow a certain probability distribution (or distribution combination) for the character set you're interested in.
  2. Because it has built-in support for non-deterministic random numbers
  3. Because it supports unicode, so you could change this to an internationalized version.

For example:

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

Carl
  • 43,122
  • 10
  • 80
  • 104
  • Note that on at least MSVC 2012, you will need to const auto randSeed = std::random_device(), then pass randSeed to std::default_random_engine(). std::random_device{}() cannot compile with this version. – NuSkooler Apr 22 '15 at 22:33
  • 12
    If you're using C++11, isn't it better to not use `rand()` in your first code snippet? – Ehtesh Choudhury Aug 27 '15 at 07:24
  • C++11 allows you to separate the generator from the engine, but what is best depends on what the needs of your application are. This is why my first snippet uses rand and the second does not. – Carl Aug 31 '15 at 18:31
  • 10
    I would argue it's *never* correct to use `rand()` anymore. It's not even uniform for crying out loud... – jeremyong Oct 20 '16 at 22:50
  • @jeremyong And I would argue that the distribution of the data is not even part of the question. Further, the answer is not to give you something to copy paste into production code. The answer is merely to illustrate the different points of control you can exercise during random string generation. – Carl Jul 27 '17 at 04:32
  • 1
    @Carl I think in the C++ community, rand is deprecated and a well-known anti-pattern for many reasons aside from non-uniformity (see STL's talk "Rand Considered Harmful"). The abstraction of the generator from the view is a general C++ concept that I think is important to practitioners and students of C++ to learn (consider how it carries over to std::chrono, std::string_view, etc). – jeremyong Jul 27 '17 at 06:07
  • In C++11 you should also use std::array rather than C style arrays. I understand your point about the random generators but if you state you want to use C++11 you could write the example just as well using the proper tools of C++11 – Triskeldeian Aug 22 '20 at 22:17
  • 1
    I had massive issues using this with a multi threaded application. I tried to use srand everywhere, No luck. rand() always gave the same sequence of numbers.... Drove me crazy. Galik's version worked for me... – Ray Hulha Oct 29 '21 at 20:47
61

My 2p solution:

#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;
}
Galik
  • 47,303
  • 4
  • 80
  • 117
  • Maybe use `default_random_engine` instead of `mt19937`? The code would look more generic. – Velkan May 23 '17 at 06:29
  • 3
    @Velkan To be honest `std::default_random_engine` isn't something I feel good about recommending as the standard makes no guarantees about its quality, efficiency or repeatability between implementations. – Galik May 23 '17 at 09:54
  • 1
    To avoid using a char array literal and thus having to use `sizeof`, change the `auto&` to `std::string`, which gives you `std::string::length` – smac89 Jan 01 '18 at 01:19
  • I felt that accessing a `std::string` was likely to be slower because it contains an internal pointer to its data. That would mean an extra indirection that a static array does not require. Also `sizeof` can never be slower than `std::string::size` because it is a compile time constant. – Galik Mar 28 '18 at 08:02
  • You could use `std::size` on the array to avoid the `sizeof` – Chronial Apr 20 '20 at 11:34
  • 1
    @Chronial Yes indeed, that would be better. However `std::size` did not appear until `C++17` and there are still a lot of people only coding to `C++11/14` so I will leave it as it is for now. – Galik Apr 20 '20 at 11:49
  • 1
    Shouldn't `sizeof(chrs) - 2` be `sizeof(chrs) - 1`, because `uniform_int_distribution` includes the final value (it's an inclusive limit)? – Richard Whitehead Nov 11 '20 at 09:53
  • 3
    @RichardWhitehead No, because the array of characters `chars` includes the null terminator - adding `1` to its length. That means there are `sizeof(chrs) - 1` valid characters and the array index starts at `0` so the inclusive range would be `[0, sizeof(chrs) - 2]` because `sizeof(chrs) - 2` is the index of the last valid character. – Galik Nov 11 '20 at 12:38
28

Rather than manually looping, prefer using the appropriate C++ algorithm, in this case std::generate_n, with a proper random number generator:

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

This is close to something I would call the “canonical” solution for this problem.

Unfortunately, correctly seeding a generic C++ random number generator (e.g. MT19937) is really hard. The above code therefore uses a helper function template, 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};
}

This is complex and relatively inefficient. Luckily it’s used to initialise a thread_local variable and is therefore only invoked once per thread.

Finally, the necessary includes for the above are:

#include <algorithm>
#include <array>
#include <cstring>
#include <functional>
#include <random>
#include <string>

The above code uses class template argument deduction and thus requires C++17. It can be trivially adapted for earlier versions by adding the required template arguments.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • is it just deducing `std::size_t` for `std::uniform_int_distribution`? I can't see any other CTAD – Caleth Mar 17 '20 at 12:02
  • @Caleth Correct. (Why) does this surprise you? – Konrad Rudolph Mar 17 '20 at 12:02
  • I'm tempted to suggest taking `rng` as a defaulted parameter, with something like `template inline thread_local T default_rng = get_random_generator();` – Caleth Mar 17 '20 at 12:05
  • It took me a second to see it at all. I was probably mentally substituting `std::uniform_int_distribution<>`, which would be safe, but might warn about signed -> unsigned conversion. – Caleth Mar 17 '20 at 12:09
  • It should be noted that `std::random_device` may be "implemented in terms of an implementation-defined pseudo-random number engine." So your original seed might still only be 32 bits. – user1032677 Aug 01 '20 at 06:35
  • @user1032677 That’s why the code uses `std::seed_seq` with a vector of `seed_len` that’s based on the required state size, instead of simply `std::random_device`. And on systems that don’t give you non-deterministic random numbers, you can’t do better anyway. Unless you use a buggy implementation (e.g. outdated MinGW) there’s no concern. – Konrad Rudolph Aug 01 '20 at 09:37
  • @KonradRudolph But if `std::random_device` is seeded with 32 bits, no amount of `std::seed_seq` will help you get above 32 bits if you use `std::random_device`. I ended up using Boost which only implements `random_device` if its non-deterministic. – user1032677 Aug 02 '20 at 02:02
  • 1
    @user1032677 The point is that `std::random_device` is only a PRNG on platforms that don’t offer better sources of entropy, so you literally can’t do any better. I agree that it would be better if `std::random_device` weren’t implemented on platforms that lack a good source of entropy but I don’t see how that relates specifically to my answer. – Konrad Rudolph Aug 02 '20 at 15:25
  • You shouldn't subtract 1 from `strlen()` - the `uniform_int_distribution` limits are inclusive not exclusive – Richard Whitehead Nov 11 '20 at 11:10
  • Doesn't compile - The first parameter of `uniform_int_distribution` should be zero not `{}`. – Richard Whitehead Nov 11 '20 at 11:11
  • @RichardWhitehead You need to subtract 1 from the string length *because* the limits are inclusive. Otherwise you’ll include the zero termination in the output. What compiler are you using? It *should* compile, and it *doesn’t* compile when using `0`, because then you get a template deduction failure. (Except that the name of the function template `get_random_generator` needs to be renamed to `random_generator`). – Konrad Rudolph Nov 11 '20 at 12:33
  • @RichardWhitehead In fact, [it compiles on all major compilers](https://godbolt.org/z/xna774). – Konrad Rudolph Nov 11 '20 at 13:01
  • This is much better than the accepted answer. That one will create the same string if called within a single second's interval (return value of `time` remains the same) – Lorah Attkins Sep 29 '21 at 13:35
16
 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;
 }
Community
  • 1
  • 1
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
8

I just tested this, it works sweet and doesn't require a lookup table. rand_alnum() sort of forces out alphanumerics but because it selects 62 out of a possible 256 chars it isn't a big deal.

#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;
}
nly
  • 179
  • 7
  • 11
    There is no way to know how long this function will take to run. It's very unlikely, but strictly speaking, this could run indefinitely. – ctrlc-root Aug 14 '12 at 18:03
7

I hope this helps someone.

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

Output: random_str : DNAT1LAmbJYO0GvVo4LGqYpNcyK3eZ6t0IN3dYpHtRfwheSYipoZOf04gK7OwFIwXg2BHsSBMB84rceaTTCtBC0uZ8JWPdVxKXBd

D D
  • 298
  • 3
  • 10
  • 4
    This code is still broken and has several problems. Most importantly `std::srand()` should only really be called *once* at the beginning of the program (preferably the first thing in `main()`). The code, as is, will generate a lot of identical "random" strings if called in a tight loop. – Galik Sep 16 '18 at 05:18
5

Here's a funny one-liner. Needs ASCII.

void gen_random(char *s, int l) {
    for (int c; c=rand()%62, *s++ = (c+"07="[(c+16)/26])*(l-->0););
}
geza
  • 28,403
  • 6
  • 61
  • 135
5

The most suitable function in standard library is std::sample:

#include <algorithm>
#include <iterator>
#include <random>
#include <string>
#include <iostream>

static const char charset[] = 
    "0123456789"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz";

template<typename URBG>
std::string gen_string(std::size_t length, URBG&& g) {
    std::string result;
    result.resize(length);
    std::sample(std::cbegin(charset), 
                std::cend(charset),
                std::begin(result),
                std::intptr_t(length),
                std::forward<URBG>(g));
    return result;
}

int main() {
    std::mt19937 g;
    std::cout << gen_string(10, g) << std::endl;
    std::cout << gen_string(10, g) << std::endl;
}

State of random number generator should be kept outside of the function between calls.

Tomilov Anatoliy
  • 15,657
  • 10
  • 64
  • 169
  • Note, that `std::sample` implementation is not strictly specified in the Standard. Results between implementations of the standard library can vary (and actually vary for case `libc++` vs `libstdc++`), in spite of PRNG sequences, generated by `g` are the same. – Tomilov Anatoliy Oct 28 '21 at 12:04
3
#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;
}
Oleg
  • 486
  • 6
  • 12
1

Let's make random convenient again!

I made up a nice C++11 header only solution. You could easily add one header file to your project and then add your tests or use random strings for another purposes.

That's a quick description, but you can follow the link to check full code. The main part of solution is in class 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 incapsulates all random stuff and you can add your own functionality to it easily. After we have Randomer, it's very easy to generate strings:

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

Write your suggestions for improvement below. https://gist.github.com/VjGusev/e6da2cb4d4b0b531c1d009cd1f8904ad

Gusev Slava
  • 2,136
  • 3
  • 21
  • 26
0

Something even simpler and more basic in case you're happy for your string to contain any printable characters:

#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
}
Nobilis
  • 7,310
  • 1
  • 33
  • 67
  • 1
    I suppose this is the simplest solution and absolutely suitable for the case with specified character set – VolAnd Jul 21 '17 at 19:07
  • If you seed inside the function based on the time, you can easily get a bunch of the same random number if this is called in a loop. A better approach is to seed once per process run, but then the same problem happens if you run the process multiple times in a tight loop. Other answers are better, even if you really don't care about prng quality and don't mind using `rand`. – ggorlen Oct 26 '21 at 21:05
0

Example for Qt use:)

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

Yet another adaptation because none of the answers would suffice for my needs.

First of all, if rand() is used to generate random numbers you will get the same output at each run. The seed for random number generator has to be some sort of random.

With C++11 you can include the random library and you can initialize the seed with random_device and mt19937. This seed will be supplied by the OS and it will be random enough for us (for example, clock). You can give a range boundaries to be included ([0,25] in my case`.

I only needed random string of lowercase letters so I utilized char addition. The pool of characters approach did not work out for me.

#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;
}
ggorlen
  • 44,755
  • 7
  • 76
  • 106
Barkin Kaplan
  • 31
  • 1
  • 4
0

You can use the random() method to generate a basic random string. The code below generates a random string composed of lowercase letters, uppercase letters and digits.

String randomStrGen(int numChars){
  String genStr="";
  int sizeStr=0;
  
  while(sizeStr<numChars){
    int asciiPos= random(48,122);
    if((asciiPos>57 && asciiPos<65) || (asciiPos>90 && asciiPos<97))
      continue;
    genStr+=(char) asciiPos;
    sizeStr++;
  }
  
  return genStr;
}

if one needs a more secure random number generator, simply replace the random() function for a more secure one.

Also, one can also tweak the possible characters generated by changing the ASCII limits (48,122) to another custom values

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Miguel Tomás
  • 1,714
  • 1
  • 13
  • 23
  • 1
    For those wondering, [`random` is POSIX](https://stackoverflow.com/a/18726221/6243352) and not part of the standard library – ggorlen Oct 26 '21 at 20:44
-1

Random string, every run file = different 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);
Nehigienix
  • 53
  • 4
  • 1
    This is undefined behavior, because `std::generate_n` will assume the `custom_string` has length `LENGTH_NAME`, but it does not. – Cornstalks Feb 01 '16 at 14:57
-2

Be ware when calling the function

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

(adapted of @Ates Goral) it will result in the same character sequence every time. Use

srand(time(NULL));

before calling the function, although the rand() function is always seeded with 1 @kjfletch.

For Example:

void SerialNumberGenerator() {

    srand(time(NULL));
    for (int i = 0; i < 5; i++) {
        cout << gen_random(10) << endl;
    }
}
Community
  • 1
  • 1
Mr.Sheep
  • 1,368
  • 1
  • 15
  • 32
-2
#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;
}
ras
  • 1
-3
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';
}
-3
//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;
}
JK25
  • 1
  • 1