Is it possible to randomly call subprograms?

I have a program that has ten subprograms, each of which contains a randomly generated sentence.
The subprograms are called sentence0, sentence1, sentence2 etc.

However, I only want to use one of them at random.

I've been trying to figure out a way of doing this.
I've tried using a switch statement using this code in visual studio.
int sentence1 = rand()%8;
switch (sentence1)
case 0:
sentence0Gen(history, 500, attributes, 5);
case 1:
sentence1Gen(history, 500, attributes, 5);
case 2:
sentence2Gen(history, 500, attributes, 5);
case 3:
sentence3Gen(history, 500, attributes, 5);
case 4:
sentence4Gen(history, 500, attributes, 5);
case 5:
sentence5Gen(history, 500, attributes, 5);
case 6:
sentence6Gen(history, 500, attributes, 5);
case 7:
sentence7Gen(history, 500, attributes, 5);

For some reason, this does not work. It compiles, but when I cout history after the sentences have added to it, it doesn't work.

After some debugging, for some weird reason, it does work if sentence1=0, but no other number.

Can someone see why this does not work?

Are you actually modifying history in the functions and not just a parameter?
can you post the implementation of the sentence functions? additionally, (i doubt this is the cause though), have you seeded the rng?
Sure Jaded. As you can see, I'm passing two arrays and their sizes.

Attributes is just used for some calculations in the array.

history is strcat'd onto.

Some sentences are really long, the shortest one is this:

void sentence6Gen(char history[], int size, int attributes[], int size2)
// hates
int randomPart1=rand()%3;
// the random number for the first part of the sentence
int randomPart2=rand()%6;
// the random number for the second part of the sentence
char part1[10][100] =
"He cannot stand ",
"There is nothing he hates more than ",
"He is planning to destroy "
// the first part of the sentence
char part2[20][50] =
"cats.\n", "rainbows.\n", "the police.\n", "blondes.\n", "the irish.\n",
"butterflies\n", "bald men\n", "musicals.\n", "fast food restaurants.\n",
"alcoholics.\n", "skinny people.\n", "non-believers.\n", "greasers.\n"
strcat(part1[randomPart1], part2[randomPart2]);
// the two parts are randomly added together in an array.
strcat(history, part1[randomPart1]);
// the total is added to the overall character history.

Ultimately, history is modified.

Later, in the subprogram which calls the sentences I cout the entire history array with this for loop:

for (int i=0;i<500;i++)
cout << history[i];
if (history[i+1] == '\0')
// this stops the array displaying anything after the null character.

If I were to just call the subprogram normally, it couts perfectly, only with all the sentences. I only want one.

The curious thing here is that if it is set to zero on the switch statement, it works. Also, individually calling the subprograms in any order works as well.

I don't even know what seeding the rng is, I'm new to this, thanks for the suggestion though
Last edited on
This may not be the case, but I suspect the cause is one of the following:

--Concatenation is including the terminating null character,
--The size isn't being updated after the concatenation (pass the size variables by reference and modify them inside the function)
--The arrays allocated memory is unable to contain all of the concatenated content.

Seeding the rng can be read about here:
--Note: easy way to seed the rng (do this once on each program run)

Below are some tips for C++, which will make things a LOT easier for you. I strongly recommend you become familiar with them, but dont rush too much. Try using the string class for now, and you can play with vectors later, if you bite more than you can chew you'll quickly get sick of programming.

#include <stdlib.h>
#include <time.h>
// ....
  srand ( time(NULL) );

Since you are using C++, I strongly recommend using the string class, instead of c-style strings. The string class automatically manages the size, it simplifies usage with the functions given, and (this one is important), it acts as a wrapper. Read about it here:
example string declaration: "std::string myString = "Hello World!";"

And, in cases like this, the vector class is also very useful. It acts similar to arrays, but also contains the size, and you dont have a fixed size. Example declarations of a vector:

"std::vector<std::string> myStrings; "
"std::vector<int> myInts; "

Related reading:

Read these examples and then try to use a vector, it greatly simplifies situations like this.

I know thats a lot of reading, but it is well worth it. Good luck!
Thanks, but this is for a project, and we're not allowed to use the string class, the entire thing has to be done in arrays. Why, I don't know. My course is cruel.

Luckily, they aren't restricting us to switch statements. We can use if statements repeatedly, although it will look messy and it is possible to have the same reaction.

There is only one other way I can think of that will solve it.

Is there a way of using an integer in the call of a subprogram?

The normal calls are
sentence0gen(history, 500, attributes 5)
sentence1gen(history, 500, attributes 5)
sentence2gen(history, 500, attributes 5)

The dream call that will solve all my problems will be
sentence'randomNumber'Gen(history, 500, attributes, 5);
Last edited on
As a general rule, if you find yourself writing identifiers with sequential numbers in them, it's because what you're doing can be done better with arrays.

Would it be possible to call sentencegen(a,b,c,d,X) rather than sentenceXgen(a,b,c,d), and merge all the different versions of sentenceXgen() into it?
Merge all subprograms into one?
I don't think it would be. Each subprogram modifies the history array, and I'll still have no idea how to access them in different orders. Not only that, but some of the sentences are complicated and hundreds of lines long, while others are as short as the one I posted here. For the sake of the reader, I would try and separate them as much as possible.
Hi, I have reviewed this, since I was in a hurry previously. These two parts are likely causing errors

for (int i=0;i<500;i++)
cout << history[i];
if (history[i+1] == '\0')
// this stops the array displaying anything after the null character.

History is an integer array, not a c style string. The particularly nasty part about this one is that the terminating character has an asci code of zero, which means that whenever the integer contained in the array is zero, it will break. The reason why this isn't the case with c style strings is because the asci codes of numbers are not zero.
'0' has an asci code of 48, which means:
char ch = 48;
char ch = '0';

Are the same. Additionally...
int number = 0;
int number = '\0';

are equal as well. Be careful with integer arrays. If you want to iterate through an integer array, pass the size as another variable, and then use a for loop, ie...
void something(int *array, int size)
for(unsigned short i = 0; i < size; i++)
std::cout << "number: " << array[i] << std::endl;

history is strcat'd onto.

Once again, int arrays are not c style strings. Additionally, be careful with its usage, and the size of your c string. Since c strings are arrays of chars with a terminating character, if you truncate that character, or attempt access/modify an out-of-bounds element, the program has undefined behaviour.
Last edited on
Not only that, but some of the sentences are complicated and hundreds of lines long, while others are as short as the one I posted here. For the sake of the reader, I would try and separate them as much as possible.
Then this is a different problem altogether. You should move some of that data to a file
Hey guys, I sorted the problem out.

I don't know why, but if I used a switch statement, the first subprogram used had to strcpy onto history, rather than strcat it. I had to rewrite them slightly, turning them from voids to char *, that way I could return the string as a char*. Then I could strcpy and strcat in the main, rather than in each subprogram. This actually worked, and now I can call them randomly.

Thanks for your help though, I learned a lot
You can avoid having to differentiate between strcpy and strcat by initializing history with a null string.
  strcpy (history, "");

After that, all the random functions can do strcat.
Topic archived. No new replies allowed.