I am trying to make a function that randomly chooses a single argument to return from a variable number of arguments of a single datatype.
I am running Windows 7, and I am using Microsoft Visual C++ 2010 Express
Currently, the function is called like so:
|
char a = choose('a','b','c',NULL);
|
This should (and does) assign a random character from the given arguments to
a.
In this case,
a would ultimately equal
'a',
'b', or
'c'.
The final argument should always be NULL. The function will continue to check arguments for possible return values until the argument NULL is found.
The problem arises when I want to use a value equivalent to zero as an argument, such as the
integer 0 or the
character '\0'.
The function simply ignores the zero (or '\0'), as well as any arguments following it.
For example:
|
int b = choose(5, 9, 3, 0, 17, 16, 92, NULL);
|
This will assign either
5,
9, or
3 to the variable
b. Everything after
0, including
0 itself, is completely ignored. This is obviously not how the function is supposed to behave.
It would seem that 0, NULL, and '\0' all have equivalent values, so if any of them are entered before the true final argument, then they are recognized as the final argument, and all arguments after them are ignored accordingly.
I've tried replacing NULL with
(char)1, but that yielded the same issue, only with ones being excluded instead of zeroes.
Is there something other than NULL that I could use for my final argument that wouldn't yield such an issue? (such as a constant value that can only be obtained by explicitly entering its name)
I would prefer a solution that would still support the use of a template, but if that's impossible, then I'll take what I can get.
Thanks in advance; your help will be appreciated.
Here is the code for the function itself:
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 30 31 32 33 34 35 36
|
template <typename T>
T choose (T arg1, ...)
{
int argsCount = 0; //the number of arguments
va_list list; //declares the variable argument list
va_start(list,arg1); //starts the variable argument list
T currentArg; //the current argument within the loop
do //a do while() loop is used instead of a while() loop just in case the garbage in currentArg is a NULL character
{
currentArg = va_arg(list,T); //assign the value of the current argument in the list to currentArg
if (currentArg != NULL)
{
argsCount++; //increment the number of arguments
}
} while(currentArg != NULL); //while the current argument is not NULL. This loop gets the number of arguments.
va_end(list); //resets the variable argument list to NULL so that it can be called again properly
int choice = random.roll_range(-1, argsCount - 1); //sets the location of the choice in the list to a random int >=-1 and <=argsCount. If -1, then return the first argument.
if ( choice == -1 )
{
return arg1; //returns arg1, the first argument in the function call
}
else //if choice is not -1, then an argument from the variable argument list must be chosen.
{
va_start(list,arg1); //starts the variable argument list again
for( int i = 0; i < argsCount; i++ )
{
T currentArg = va_arg(list,T); //assign the value of the current argument in the list to currentArg
if (i == choice)
{
return currentArg; //returns the chosen argument
}
}
va_end(list); //resets the variable argument list to NULL
return NULL; //returns NULL if the function failed to choose an argument
}
}
|
Note: random.roll_range returns a random integer between two integer parameters, min and max. I know for a fact that this is not where the issue is occurring, but just in case it is necessary, here is the code for random.roll_range:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
int CRandom::roll_range(int min, int max)
{
if ( min < max )
{
return ( rand() % (max + 1 - min) ) + min;
}
else if ( min > max ) //This ensures the function will behave properly even if the arguments were entered backwards
{
return ( rand() % (min + 1 - max) ) + max;
}
else //If both arguments are equal, then it does not matter which is returned, so return max.
{
return max;
}
}
|