There are several issues of varying severity, and here's my best attempt at flagging them:
int shuffledArray[userSize];
This array has a variable length. I don't think that it's as bad as other users point out, but you should know that this isn't allowed by the C++ standard, so you can't expect it to work on every compiler that you try (GCC and Clang will let you do it, but MSVC won't, for instance).
srand(time(0));
This is most likely outside the scope of your assignment (you've probably been told "use rand
/srand
" as a simplification), but rand
is actually a terrible random number generator compared to what else the C++ language offers. It is rather slow, it repeats quickly (calling rand()
in sequence will eventually start returning the same sequence that it did before), it is easy to predict based on just a few samples, and it is not uniform (some values have a much higher probability of being returned than others). If you pursue C++, you should look into the <random>
header (and, realistically, how to use it, because it's unfortunately not a shining example of simplicity).
Additionally, seeding with time(0)
will give you sequences that change only once per second. This means that if you call shuffle_array
twice quickly in succession, you're likely to get the same "random" order. (This is one reason that often people will call srand
once, in main
, instead.)
for(int i = userSize - 1; i > 0; i--)
By iterating to i > 0
, you will never enter the loop with i == 0
. This means that there's a chance that you'll never swap the zeroth element. (It could still be swapped by another iteration, depending on your luck, but this is clearly a bug.)
int randomPosition = (rand() % userSize);
You should know that this is biased: because the maximum value of rand()
is likely not divisible by userSize
, you are marginally more likely to get small values than large values. You can probably just read up the explanation and move on for the purposes of your assignment.
return shuffledArray;
This is a hard error: it is never legal to return storage that was allocated for a function. In this case, the memory for shuffledArray
is allocated automatically at the beginning at the function, and importantly, it is deallocated automatically at the end: this means that your program will reuse it for other purposes. Reading from it is likely to return values that have been overwritten by some code, and writing to it is likely to overwrite memory that is currently used by other code, which can have catastrophic consequences.
Of course, I'm writing all of this assuming that you use the result of shuffle_array
. If you don't use it, you should just not return it (although in this case, it's unlikely to be the reason that your program crashes).
Inside a function, it's fine to pass a pointer to automatic storage to another function, but it's never okay to return that. If you can't use std::vector
(which is the best option here, IMO), you have three other options:
- have
shuffle_array
accept a shuffledArray[]
that is the same size as initialArray
already, and return nothing;
- have
shuffle_array
modify initialArray
instead (the shuffling algorithm that you are using is in-place, meaning that you'll get correct results even if you don't copy the original input)
- dynamically allocate the memory for
shuffledArray
using new
, which will prevent it from being automatically reclaimed at the end of the function.
Option 3 requires you to use manual memory management, which is generally frowned upon these days. I think that option 1 or 2 are best. Option 1 would look like this:
void shuffle_array(int initialArray[], int shuffledArray[], int userSize) { ... }
where userSize
is the size of both initialArray
and shuffledArray
. In this scenario, the caller needs to own the storage for shuffledArray
.