Help with random_shuffle function

I am new to programming with C++, so would appreciate help with the following:

I am using random shuffle to randomly order an array. If I have an array such as:

int xarray[] = {1, 2, 3, 4, 5};

Then using the following code:

int arrlength = sizeof(xarray)/sizeof(xarray[0]);
random_shuffle(&xarray[0], &xarray[arrlength-1]);

Returns:

X X X X 5

Using random_shuffle will always return the last value as 5. So while the first four digits will be randomised, the final digit remains the final digit as specified in the original array. I haven't read of this problem on any forums so I am wondering whether there is an obvious problem I am missing with this? I could add a dummy value to the end of my array but I don't particularly wish to do that. (Incidently, am seeding using srand(time(NULL)).)
A simpler way to use random_shuffle() is by using pointer arithmetic:

1
2
//            [begin]  [      end        ]
random_shuffle(xarray, xarray + arrlength);


From the example above you should notice something odd: the end is not the address of the last element in the array.

Instead it is the address of the imaginary element just past the last element.
This is the C++ style of iteration. For one, it allows for elegant code, as seen above we have no -1 correction.

And it also allows for "natural" iteration until the end was reached:

while (iterator != end)
{
    do something

    ++iterator
}

// when end is reached, the while stops, but that's OK because
// the end isn't an element anyway


Edit: small typos, and corrections.
Last edited on
Thanks Catfish666. Problem solved. A great help.
I hope it's not too late if I link to the documentation now:
http://www.cplusplus.com/reference/algorithm/random_shuffle/

Reference wrote:
template <class RandomAccessIterator>
void random_shuffle (RandomAccessIterator first, RandomAccessIterator last);

Parameters

first, last
Random-access iterators to the initial and final positions of the sequence to be shuffled. The range used is [first,last), which contains all the elements between first and last, including the element pointed by first but not the element pointed by last.


Note the open end of the interval: [first, last) all algorithms follow this rule and by extension all container iterators. See for example std::vector::end():
http://www.cplusplus.com/reference/vector/vector/end/

As a C++ programmer, you will eventually start using containers instead of C style arrays, which is the natural thing to do.
http://www.cplusplus.com/reference/stl/

Here's a fancy rewrite of your program, in the C++11 dialect (C++ standard of year 2011).
Note that you need a modern compiler to successfully compile this: GNU GCC 4.7+, Visual Studio 2013.
Possibly problematic features are marked by comments.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> vi {1, 2, 3, 4, 5}; // C++11 initializer list

    std::srand(std::time(nullptr)); // C++11 null pointer
    std::random_shuffle(vi.begin(), vi.end());

    for (int i: vi) // C++11 range-based for() loop
        std::cout << i << ' ';

    std::cout << std::endl;
}


Last edited on
Topic archived. No new replies allowed.