Randomly Generating String Length

I'm trying to randomly generate a series of letters from a character pool A-Z, but want the string length to vary every time I run the compiler.

This is the function that i have for now:

1
2
3
4
5
6
7
8
9
10
11
12
char gibberish()
{
  srand(time(0));
  char c;
  int r; 
  for(int i = 5; i < 5; i++)
 {
   r = rand()%26;
   c = 'A' + r;
   cout<<c;
  }
}


When seeing the output of c, i find that the length of the random letters generated is 7 every single time, which i realized is the difference of the 3 and 10. I want that every time I generate this, the number of letters generated is either greater than or equal to 5, or less than or equal to 7. Which was why my for loop was set up the way it was.

Anybody have ideas how i can randomly generate the length of the output as well and incorporate it to 'c' ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <chrono>
#include <iostream>
#include <random>
#include <string>

std::string gibberish()
{
  static std::ranlux48 rng( std::chrono::system_clock::now().time_since_epoch().count() );
  static std::uniform_int_distribution<int> rnd57( 5, 7 );
  static std::uniform_int_distribution<char> rndAZ( 'A', 'Z' );
  std::string s( rnd57( rng ), 0 );
  for (char& c : s) c = rndAZ( rng );
  return s;
}

int main()
{
  // Generate 10 gibberish strings:
  for (int n = 0; n < 10; n++)
    std::cout << gibberish() << "\n";
}
char c;
If you create a single char, you can store ONE character in it. Just ONE. There is no way you can store many characters in it.

As DuThomhas demonstrates, if you want a string, use a string.
An easier version than Duthomhas'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>

std::string gibberish(int len)
{
  std::string s(len, ' ');
  for (int i = 0; i < len; i++)
    s[i] = 'A' + (rand() % 26);

  return s;
}

int main() 
{
  srand(static_cast<unsigned int>(time(nullptr)));

  for (int i = 0; i < 10; i++)
  {
    std::cout << gibberish(4 + (rand() % 10)) << "\n";
  }
}
1
2
3
for(int i = 5; i < 5; i++)
{
}

When seeing the output of c, i find that the length of the random letters generated is 7 every single time, which i realized is the difference of the 3 and 10.

The loop in your never evaluates its body, because 5 is never less than 5.
Your code has no 3, no 7, nor 10 anywhere.

either greater than or equal to 5,
or less than or equal to 7.

Every number is (5 <= x) or (x <= 7). Lets take 42. It is not less than 7, but it is more than 5. The OR says that that is enough.

Perhaps you mean (5 <= x) and (x <= 7)? With AND both subconditions must be true simultaneously. In math you could express that with 5 <= x <= 7, but C++ requires the and.

There is no half a char, so integers. You want length of 5, 6, or 7?

The for (int i = 0; i < len; i++) repeats len times.
The rnd57( rng ) in Duthomas code is similar to a call to rand() that returns 5, 6, or 7.

Thomas code 4 + (rand() % 10) does ...
the rand() % 10 returns 0, 1, .. 9. Numbers 0--9.
With the +4 one gets numbers 4--13.

The Duthomas version is recommended, for someone wants to remove the rand() for good.
Nevertheless, you want len to be 5+0 or 5+1 or 5+2, don't you?
Last edited on
To me it looks like one of these cases where the cure is worse than the disease.
1
2
3
4
  static std::ranlux48 rng( std::chrono::system_clock::now().time_since_epoch().count() );
  static std::uniform_int_distribution<int> rnd57( 5, 7 );
  static std::uniform_int_distribution<char> rndAZ( 'A', 'Z' );
  std::string s( rnd57( rng ), 0 );


Who want to memorize and type such a monster with meaningful names like ranlux48 ?
For his simple needs rand is good enough.
No, the cure is to know how to do something correctly. rand() is junk and you should toss it. I am honestly sick of seeing questions about it. It should have died at least twenty years ago.

I agree that the standard chrono stuff gets wordy — I consider it unnecessarily so myself — but the extra verbiage is very easy to understand and does things without the hidden gotchas that your code introduces.

ranlux48 : the random number generator I'm going to use. Substitute another if you like, like Mersenne Twister or whatever. Heck, you can even substitute rand()’s minstd_rand.

chrono::...count() : gets the current time.

uniform_int_distribution : gets numbers in a specific range without bias. I use two: one for the length of the string and one for the majuscule letters to fill it.

Your code:

1. Cheats by offloading string length randomization onto the caller
2. Uses modular arithmetic, adding bias to the results (OP will have more length-5 strings than length-7, and will get more 'A's than 'Z's).
3. Demonstrates how easy it is to get wrong. (How many characters are you asking for in the result string?)

It isn’t any easier at all, neither on the eyes nor in use. (Prefer to do it correctly if you are going to do it at all.)
Last edited on
@keskiverto ,

Sorry. I was meaning to do this:

(i = 3; i < 10; i++) so I had 7 stuck in my mind. But i forgot i changed it to 5 and I also messed up setting i = 5; which was funny because I didn't realize that. Thanks for pointing that out.


@Thomas1965
* her needs you mean. Thanks for the simplification. Will look into both Duthomas and yours.

@Duthomas

I get that. That's something to look into. Perhaps you should say that to schools as well because I'm using rand() since it was what was taught to us. Not any of the stuff you have written. And unless I don't do their "rand()" junk, I'll get points off. And I honestly didn't even know ranlux48, chrono, uniform_int_distribution exists. I imagine I chose the beginner's thread for this and so it's my first time seeing those. And I imagine the reason why you're seeing the same questions for rand() is because it's still what is taught and any of the people asking probably don't know any better like me. Thanks though. I'll definitely bring that to my professor and ask why we don't use it instead.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>

// invariant: 0 < minl && minl < maxl
std::size_t random_length( std::size_t minl, std::size_t maxl )
{
    return std::rand() % (maxl-minl) + minl + 1 ;
}

char random_char()
{
    static const std::string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
    return alphabet[ std::rand() % alphabet.size() ] ;
}

std::string random_string( std::size_t minl = 5, std::size_t maxl = 10 )
{
    std::string str( random_length( minl, maxl ), ' ' ) ;
    for( char& c : str ) c = random_char() ;
    return str ;
}

int main()
{
    std::srand( std::time(nullptr) ) ;
    for( int i = 0 ; i < 25 ; ++i ) std::cout << random_string() << '\n' ;
}

http://coliru.stacked-crooked.com/a/ac1b991be26aeb55
@teeper
Yeah, that’s exactly what bugs me: it is still taught, even knowing it is not just ancient but flat-out wrong.

I wouldn’t go so far as to give your professor any grief over it, though. He probably doesn’t care.

(Though if you do, you might want to just say that you found the Standard Random library and read online that using rand() % n produces bias via the Pigeonhole Principle, and thought it was pretty cool and just thought to share.)
@Duthomhas Will do!!! Lots of thanks :)
Registered users can post here. Sign in or register to post.