trying to shuffle a string

I'm trying to write a program that will randomly shuffle a string input by the user. At the moment it's outputting some garbage. Here's what I have so far:

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
  #include <iostream>
#include <cstring>
#include <string.h>
#include <cstdlib>
#include <ctime>

using namespace std;

//prototype of function stringMix
void StringMix(char user_string[], char empty_string[]);


int main()
{
    bool tryAgain = true;// defines tryAgain bool and sets to true
    char user_string[50];
    char empty_string[50];

    cout << "Enter a phrase here: " << endl;
    cin.getline(user_string, 50);


   //this loop continues each time the user chooses y, ends if n
    while(tryAgain == true)
    {
        StringMix(user_string, empty_string);
        cout << empty_string << endl;

        string choice;

        cout << "Would you like to reshuffle? Y or N: " << endl;
        cin >> choice;

        if (choice != "Y" && choice != "y")
        {
            tryAgain = false;
        }

      }

    return 0;
}

/******************************************************************************
                                StringMix
Uses empty_string to store a random shuffle of user_string.
******************************************************************************/
void StringMix(char user_string[], char empty_string[])
{
    unsigned seed;
    seed = time(0);
    srand(seed);

    int strLength = strlen(user_string);  //length of userString
    int randNum;    //random numbers
    char spare;     //to hold characters being switched

    int len = strLength - 1;
    int x;

    for (x = 0; len > 0; x++)
    {
        x = rand() % len;
        spare = empty_string[len];
        empty_string[len] = empty_string[x];
        empty_string[x] = spare;
        len--;

    }

    int j; //initialize int j
    //loop through elements of third array
    for (j = 0; j < strLength; j++)
    {
            //pring elements of third array
            cout << empty_string[j] << endl;
    }

}



Enter a phrase here: 
eat me

P
?
?
[
?
P??[?
Would you like to reshuffle? Y or N: 


Can someone give me a hint as to where I should go with this?
Why not just call std::random_shuffle (or std::shuffle if you don't want to be archaic)?
Oh, sorry Cubbi. I should have mentioned, It's not permissible to use built-in functions.
I've come up with solution that may satisfy your needs

1
2
3
4
5
6
7
8
9
10
void StringMix(char arr[]) // instead of making a new array we can change the original
{
    int len = strlen(arr);

    for(int i = 0; i < len; ++i) 
    {
        int random_index = random() % len; 
        arr[i] = arr[i] + arr[random_index] - (arr[random_index] = arr[i]); // we just swap two letters each time
    }
}
Last edited on
Thank you rich1. This looks promising. Maybe you could help me to understand it a little better. When I tried to implement it I got a segmentation fault. Here's my full program and output:

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <cstring>
#include <string>
#include <cstdlib>
#include <ctime>

using namespace std;

//prototype of function stringMix
void StringMix(char user_string[]);

int main()
{
    bool tryAgain = true;// defines tryAgain bool and sets to true
    char user_string[50];// user input string
    string choice;// stores user's choice y or n


    //ask user to type a phrase
    cout << "Enter a phrase here: " << endl;
    cin.getline(user_string, 50); //store user input

   //this loop continues each time the user chooses y, ends if n
    while(tryAgain == true)
    {
        //call string mix function
        StringMix(user_string);
        cout << user_string << endl;//print string

        //ask user if they would like to reshuffle
        cout << "Would you like to reshuffle? Y or N: " << endl;
        cin >> choice; //store choice

        if (choice != "Y" && choice != "y")
        {
            tryAgain = false;// if user chooses y
        }

      }

    return 0;
}

/******************************************************************************
                                StringMix
Uses empty_string to store a random shuffle of user_string.
******************************************************************************/
void StringMix(char user_string[])
{
    unsigned seed;
    seed = time(0);
    srand(seed);

    int len = strlen(user_string);  //length of userString
    int random_index;    //random position in string

    int i;
    for (i = 0; len > 0; i++)
    {
        int random_index = random() % len; //get random index
        user_string[i] = user_string[i] + user_string[random_index] -
        (user_string [random_index] = user_string[i]);
    }

}



Enter a phrase here: 
mister
Segmentation fault: 11


It's not permissible to use built-in functions.
That surely can't be true as you are using the input/output functions and the PRNG rand() and a few other functions. Maybe you mean functions you have yet to learn?

Also if you want a really basic and not very effective shuffle you could do something like

1
2
3
4
5
6
7
8
9
10

srand(time(nullptr));

for(int i = 0; i < strSize; ++i)
{
    int pos = rand() % strSize;
    char temp = str[i];
    str[i] = str[pos];
    str[pos] = temp;
}


By the way you should only seed once and at the beginning of the program.
Last edited on
Sorry, I need to learn to be a lot more precise with my statements here. It's not permissible to use built in functions for shuffling the string.

Thank you giblit. I'll give that a try.
I've checked your program and found the problem. Look at the for loop in StringMix function:
1
2
3
int i;
for (i = 0; len > 0; i++)  // condition needs to be i < len
...
rich1, I made that change and I'm still getting junk. I've tried a couple different methods of shuffling the string (including giblit's above), and I just get different kinds of junk. I'm really perplexed at this point.
What exactly are you getting that is junk?


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
#include <iostream> 
#include <string>
#include <cstdlib>
#include <ctime>

int main()
{
    std::srand(static_cast<unsigned>(std::time(nullptr)));
    
    std::string str = "";
    
    std::cout << "Please enter a string: ";
    std::getline(std::cin, str);
    
    std::size_t strSize = str.size();
    
    std::size_t const shuffles = 20;
    for(std::size_t i = 0u; i < shuffles; ++i)
    {
        for(std::size_t j = 0u; j < strSize; ++j)
        {
            std::size_t index = rand() % strSize;
            char temp = str[j];
            str[j] = str[index];
            str[index] = temp;
        }
        
        std::cout << "Shuffle " << i + 1 << " = " << str << '\n';
    }
    
    std::cout << std::endl;

    return 0;
}
Please enter a string: GIBLIT
Shuffle 1 = IIGBTL
Shuffle 2 = BGITIL
Shuffle 3 = GITIBL
Shuffle 4 = ILIBGT
Shuffle 5 = GBTILI
Shuffle 6 = TBLIGI
Shuffle 7 = LIIBTG
Shuffle 8 = IIGLTB
Shuffle 9 = BGTILI
Shuffle 10 = LIBTGI
Shuffle 11 = GLIBIT
Shuffle 12 = BGLIIT
Shuffle 13 = IIBGTL
Shuffle 14 = BLGITI
Shuffle 15 = LIGTBI
Shuffle 16 = GIIBTL
Shuffle 17 = BLIGTI
Shuffle 18 = LGITIB
Shuffle 19 = GIIBLT
Shuffle 20 = LIIBGT
As I mentioned before though this isn't a very good shuffle if you ask me. But it is something you can start with and then make the necessary fixes to.

Either way it is just a slightly modified version of your original
1
2
3
4
5
6
7
8
9
10
11
    int x;

    for (x = 0; len > 0; x++)
    {
        x = rand() % len;
        spare = empty_string[len];
        empty_string[len] = empty_string[x];
        empty_string[x] = spare;
        len--;

    }


notice how I used 2 variables though, 1 to keep track of current position and 1 for the random position.
Last edited on
Thank you again, giblit. I'm getting closer. In my version I have to use c-style strings. I like your example coda above. I wonder if you could help me understand a couple of details.

First, could you explain line 10. I have not seen a string declared this way before, where it is equal to " ".

Second, on line 18 - "size_t i = 0u". What is '0u'? I've not seen this before.
Line 10 I was just initializing the string to an empty string, I believe by default it is set to an empty one but I just like to double check.

On line 18 the u is for unsigned kind of like how f is for float.
Another alternative would be to iterate n amount of times then swap that random index with index 0.

Something like

1
2
3
4
5
6
7
for(int i = 0; i < iterations; ++i) //iterations would be best if it was >= the str size
{
    int index = rand() % strSize;
    char temp = str[0];
    str[0] = str[index];
    str[index] = temp;
}
Thank you. I got'er working.
Topic archived. No new replies allowed.