-5

I'm trying to make a random string using "ABCDEFG" or less(depends on difficulty(gonna be a game)), but my code keeps giving me errors like "multiple definition","first defined here".

I have too small experience on C++ (only worken in Java before, and app inventor..) so I guess I'm missing some c++ basic rule about strings/char/functions here.

Here is my code:

#include "Functions.h"
#include <iostream>
#include <cassert>
#include <iterator>
#include <string>
#include <ctime>
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;


 string createRandomString(int);

int main(){

string test;
test=createRandomString(1);
cout << test;
return 0;

}


string createRandomString(int stringlength){

srand(time(NULL));

string lettersToUse="ABCDEFG";
string newOne="";


for(int i=0;i<=stringlength-1;i++){
    srand(time(NULL));
    newOne=newOne+lettersToUse[rand() % 7 + 1];
}
return newOne;
}

Thank you very much for help!

  • If you are getting errors you need to show us what the exact errors are. Also what is `#include "Functions.h"` used for? – NathanOliver Feb 16 '16 at 16:36
  • 1
    Well, at the very least, you don't need to constantly keep calling srand. that will cause you to get the same value back from rand() each time until time(NULL) returns a different value. – Speed8ump Feb 16 '16 at 16:41
  • 1
    I would recommend against using `rand()`. It is problematic in many ways. You should check out the `std::random` library instead. http://en.cppreference.com/w/cpp/header/random – caps Feb 16 '16 at 17:03

3 Answers3

1

Why do you include so many unneeded header files? These should be sufficient:

#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

You should avoid using namespace std;. If you don't want to type std::string every time especially you can use using std::string;

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

Now to your function.

To avoid compiler warnings I would recommend to change srand(time(NULL)); to srand(static_cast<unsigned int>(time(NULL)));

Your loop is ok, yet you usually don't write i <= stringlength - 1 but i < stringlength

The next srand(time(NULL)); is unecessary.

The real problem is your random value: You are using rand()%7+1. rand()%7 will give give you a value of range [0,6] which would be ok, but by adding 1 the range moves to [1;7] and 7 is outside of your lettersToUse string.

To be safe you should limit the range to what is actually accessible. lettersToUse.size() is 7 in your case. As we saw before rand()%7 gives you the correct range. So going with rand()%lettersToUse.size() will always be ok as long as lettersToUse.size() is not 0.

#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

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


string createRandomString(int);

int main() {

    string test;
    test = createRandomString(1);
    cout << test;
    return 0;

}


string createRandomString(int stringlength) {

    srand(static_cast<unsigned int>(time(NULL)));

    string lettersToUse = "ABCDEFG";
    string newOne = "";

    for (int i = 0; i < stringlength - 1; i++) {
        newOne += lettersToUse[rand() % lettersToUse.size()];
    }
    return newOne;
}

If you attempt to modify lettersToUse or even allow a user to specify lettersToUse, you should definitaly add a check for the size of letterToUse as the program will crash when it's empty.

If you can use C++11 I would recommend to use the C++ random number generator provided by it:

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

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


string createRandomString(int);

int main() {

    string test;
    test = createRandomString(5000);
    cout << test;
    return 0;

}


string createRandomString(int stringlength) {
    string lettersToUse = "ABCDEFG";
    string newOne = "";

    std::default_random_engine generator;
    std::uniform_int_distribution<int> distribution(0, lettersToUse.size()-1); //Range from [0-6], when size is 7: 0-6 = 7 elements

    for (int i = 0; i < stringlength - 1; i++) {
        newOne += lettersToUse[distribution(generator)];
    }
    return newOne;
}

As recommended by caps here is the version using std::generate_n:

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

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


string createRandomString(int);

int main() {

    string test;
    test = createRandomString(1);
    cout << test;
    return 0;

}


string createRandomString(int stringlength) {
    string lettersToUse = "ABCDEFG";

    std::default_random_engine generator;
    std::uniform_int_distribution<int> distribution(0, lettersToUse.size() - 1); //Range from [0-6], when size is 7: 0-6 = 7 elements

    string newOne;
    newOne.reserve(stringlength);
    std::generate_n(std::back_inserter(newOne), newOne.capacity(), [&lettersToUse, &distribution, &generator]() { return lettersToUse[distribution(generator)]; });

    return newOne;
}
Simon Kraemer
  • 5,700
  • 1
  • 19
  • 49
  • 1
    Don't use C-style casts. Rather than `(unsigned int)time(NULL)` you should be doing something like `static_cast(time(NULL))`. – caps Feb 16 '16 at 17:02
  • @caps Updated. Thank you. – Simon Kraemer Feb 16 '16 at 17:06
  • Update is way better. +1 EDIT: Well, `rand()` use is still awful, but otherwise, new answer is decent. – caps Feb 16 '16 at 17:07
  • @caps There is no random number generator in C++<11, is there? – Simon Kraemer Feb 16 '16 at 17:12
  • `std::default_random_engine` and `std::uniform_int_distribution` are both in the `std::` library as of C++11, but not before. If I were forced to write in C++03 or earlier, I would use `boost::random` which has almost the same interface: http://www.boost.org/doc/libs/1_60_0/doc/html/boost_random.html – caps Feb 16 '16 at 17:14
  • I would also suggest using `std::generate_n` with a lambda instead of the raw `for` loop. – caps Feb 16 '16 at 18:40
  • Working perfectly fine after this, I lost hope when I got the same errors after I checked c++11 in compiler options, but reseting codeblocks did the work. Thank you! – BlackFolgore Feb 17 '16 at 03:20
  • 1
    @caps Added your recommendation – Simon Kraemer Feb 17 '16 at 08:54
0

In your loop srand(time(NULL)); give you the same random value every time. And what is #include "Functions.h" used for? i erase the header file also.

Here is your complete code:This function generate a random string.

#include <iostream>
#include <cassert>
#include <iterator>
#include <string>
#include <ctime>
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;


 string createRandomString(int);

int main(){

string test;
test=createRandomString(6);
cout << test;
return 0;

}
string createRandomString(int stringlength){

srand(time(NULL));

string lettersToUse="ABCDEFG";
string newOne="";
for(int i=0;i<=stringlength-1;i++){
    newOne=newOne+lettersToUse[rand() % lettersToUse.length()];
}
return newOne;
}

Output: DFEEDD

Prosen Ghosh
  • 635
  • 7
  • 16
-1

Regarding your error I can't say anything because you don't mention them. Regarding how to create a random string, this have been already asked here, I paste Ates Goral code which I think is the simplest:

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

A couple of things about your code:

  • You use a lot of C libraries. This is something you should avoid as much as possible IMO - you're in C++, so use C++ functionality.. there's a random header in C++ for instance -> have a look here
  • when you do include C libraries be careful what version are you including. In C++ you have two options, the XXX.h header (e.g. math.h) which you should not normally use unless there is some very specific reason, and the cXXXX version (e.g. cmath) which is the one you should normally use. The former is the C library as is, the latter is the C library optimised for use in C++, short of. It makes proper use of namespaces and has subtle implementation differences etc. In general with the latter you have guarantees that you don't necessarily have with the raw C headers.
  • it's not considered a good practice to use namespace std the way you do, you may want to google it for more info.
Community
  • 1
  • 1
Marinos K
  • 1,779
  • 16
  • 39
  • You are "complaning" that OP uses C libraries, yet your answer uses C-Style arrays instead of `std::string`.... – Simon Kraemer Feb 16 '16 at 17:01
  • @SimonKraemer I pasted the simplest answer and a link to a whole thread which also includes more c++-style solutions. I just thought that this particular one would be easier for them to immediately use. – Marinos K Feb 16 '16 at 17:20