-2

I'm trying to create a random string generator. I create a random length from 1 - 50 with this

randomLength = rand() % kMaxRandomString + kMinRandomString;

then, I create a char pointer with new to hold it like this:

char* stringBuff = new char[randomLength];

After all that put together I created a vector to hold all possible characters. The whole block of code together looks like this.

void randomStringGen(char * pString)
{
  vector <string> alphaChar
  {
      R"(ABCDEFGHIJKLMNOPQRSTUVWXYZ)",
      R"(abcdefghijklmnopqrstuvwxyz)",
  };

  int randomLetterRow = 0;
  int randomLetterColm = 0;
  int randomLength = 0;
  srand(time(NULL));
  randomLength = rand() % kMaxRandomString + kMinRandomString;
  char* stringBuff = new char[randomLength];
  string test;
  for (int i = 0; i < randomLength; i++)
  {
      randomLetterRow = rand() % 2 + 1; //this chooses a row (lowercase or upper)
      randomLetterColm = rand() % 26 + 1; //this chooses a random letter from the row
      *stringBuff = alphaChar[randomLetterRow][randomLetterColm]; //I try to add the letter to the string
  }
  pString = stringBuff;
}

Everything seems to work, except for

 *stringBuff = alphaChar[randomLetterRow][randomLetterColm];

Which is the whole important part. I've tried countless ways to do it. I tried with strcpy(), I tried just using a char array[].

Robolisk
  • 1,682
  • 5
  • 22
  • 49
  • 1
    What tells you it's wrong? That would save us some computing power... – LogicStuff Apr 12 '16 at 19:25
  • What goes wrong? What are the values of the sizes? No complete minimal example created? :/ – gsamaras Apr 12 '16 at 19:25
  • Why this approach? Create a vector with your random size, fill it with random index'ed characters from a prepared string "ABC...Zabc..z" or an alphabet container. So pick a random number between 0 and 54 as the random index for a chosen "random" character, fill all elements of your vector using this strategy. – Khalil Khalaf Apr 12 '16 at 19:26
  • 2
    Does you function have to be in the form of `void randomStringGen(char * pString)`? It would be a lot easier more C++y if you could return a `std::string` by value. (`std::string randomStringGen()`) – NathanOliver Apr 12 '16 at 19:29
  • The big shock will be when it looks like it "works" but assigning a new address to `pString` does nothing for the calling function. – Austin Mullins Apr 12 '16 at 19:30
  • I found a solution, which made my life alot easier – Robolisk Apr 12 '16 at 19:32
  • Please don't use `rand`. – Jesper Juhl Apr 12 '16 at 20:08

3 Answers3

1

Using std::strings and C++11 <random> functions you can also write something like this:

#include <iostream>
#include <string>
#include <random>

using std::string;
using std::cout;

const string ALPHABET{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" };
std::random_device rd;

struct RandomString {

    RandomString( size_t min, size_t max, const string &alph = ALPHABET ) : 
        alphabet(alph), engine(rd()),
        random_size(min, max), random_char(0, alph.size() - 1) {}

    string operator()( size_t size = 0 ) {
        string str;
        if ( size == 0 ) {
            size = random_size(engine);
        }
        str.resize(size);
        for ( size_t i = 0; i < size; ++i ) {
            str[i] = alphabet[random_char(engine)];
        }
        return str;
    }

    private:
    const string alphabet;
    std::mt19937 engine;
    std::uniform_int_distribution<size_t> random_size,
                                          random_char;
};

int main() {

    RandomString rstr(3,10);

    for ( int i = 0; i < 5; ++i ) {
        cout << rstr() << '\n';            // random string of length 3 to 10
    }

    for ( int i = 1; i < 6; ++i ) {
        cout << rstr(i) << '\n';           // random string of length i
    }

    RandomString rhstr(4,12,"0123456789ABCDEF");  // change alphabet
    for ( int i = 0; i < 5; ++i ) {
        cout << "0x" << rhstr() << '\n';
    }

    return 0;
}

Which gives outputs like:

vnHlW
hscNMCTpU
ouxIwIjp
STQ
MvPyPh
t
vt
YtJ
BMWM
CmZkN
0xA047CFE
0xD95E88B
0xAB0E38CA7
0x98AE7C5A634
0xACCDA320
Bob__
  • 12,361
  • 3
  • 28
  • 42
0

The problem is that this statement:

 randomLetterRow = rand() % 2 + 1;

Can sometimes produce a value of 2 which would be a subscript out of range (trying to get the third row that doesn't exist)

Similar risk with:

randomLetterColm = rand() % 26 + 1;

There are a couple of other items that will cause this program not to work:

  • The pointer should be passed by reference if you want it changed by the function
  • stringBuff should have an index. Rather stringBuff[i] = than *stringBuff =

So a fully working program might be:

#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <ctime>

using std::vector;
using std::string;

void randomStringGen(char*& pString)
{
    vector <string> alphaChar
    {
        R"(ABCDEFGHIJKLMNOPQRSTUVWXYZ)",
        R"(abcdefghijklmnopqrstuvwxyz)",
    };

    int randomLetterRow = 0;
    int randomLetterColm = 0;
    int randomLength = 10;
    //srand(time(NULL));
    std::srand(std::time(0));
    //randomLength = rand() % kMaxRandomString + kMinRandomString;
    char* stringBuff = new char[randomLength];
    string test;
    for (int i = 0; i < randomLength; i++) {
        randomLetterRow = rand() % 2; //this chooses a row (lowercase or upper)
        randomLetterColm = rand() % 26; //this chooses a random letter from the row
        stringBuff[i] = alphaChar[randomLetterRow][randomLetterColm]; //I try to add the letter to the string
    }
    pString = stringBuff;
}

int main()
{
    char* letters{nullptr};
    randomStringGen(letters);
    return 0;
}

As mentioned in the comments this becomes much easier if we use a std::string as the parameter:

#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <ctime>

using std::vector;
using std::string;

void randomStringGen(std::string& mystring)
{
    vector <string> alphaChar
    {
        R"(ABCDEFGHIJKLMNOPQRSTUVWXYZ)",
        R"(abcdefghijklmnopqrstuvwxyz)",
    };

    int randomLetterRow = 0;
    int randomLetterColm = 0;
    int randomLength = 10;
    //srand(time(NULL));
    std::srand(std::time(0));
    //randomLength = rand() % kMaxRandomString + kMinRandomString;
    string test;
    for (int i = 0; i < randomLength; i++) {
        randomLetterRow = rand() % 2; //this chooses a row (lowercase or upper)
        randomLetterColm = rand() % 26; //this chooses a random letter from the row
        mystring.push_back(alphaChar[randomLetterRow][randomLetterColm]); //I try to add the letter to the string
    }
}

int main()
{
    std::string letters{};
    randomStringGen(letters);
    return 0;
}
wally
  • 10,717
  • 5
  • 39
  • 72
0

I couldn't find a way to do this with a string, so I had to choose a fix size for the arrays. I would have liked it to be dynamic, but this works.

int main(void)
{
  char pString[51] = "";
  for (int i = 0; i < 4; i++)
  {
    randomStringGen(pString);
    printf("random string: %s ",pString);
  }

return 0;
}

I got rid of the vector for this reason, and just created a char array to make it easier this way.

void randomStringGen(char * pString)
{
  char alphaChars[53] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  int randomLetter = 0;

  int randomLength = 0;
  srand(time(NULL));
  randomLength = rand() % kMaxRandomString + kMinRandomString;
  char stringBuff[kMaxRandomString + 1] = "";
  for (int i = 0; i < randomLength; i++)
  { 
      randomLetter = rand() % 52 + 0;
      stringBuff[i] = alphaChars[randomLetter];
  }
  strcpy(pString, stringBuff);
}
Robolisk
  • 1,682
  • 5
  • 22
  • 49