-2

Want to shuffle char *array and make elements random order

I read Shuffle array in C but for int

I try

const char *words = { "one", "two", "three", "four", "five", "six" }; 
for (int i=0; i<6; i++)
{
    int r = (rand() % (6 - i)) + i;

    int temp =  words[i];
    words[i] = words[r];
    words[r] = temp;
}

error though when iterate array words

please explain

2 Answers2

4

As said in remarks you have several problems

const char *words = { "one", "two", "three", "four", "five", "six" }; 

is invalid because the initialization (and the rest of the code) indicates words is an array, so replace it by

const char *words[] = { "one", "two", "three", "four", "five", "six" }; 
    int temp =  words[i];
    words[i] = words[r];
    words[r] = temp;

words is an array of const char * so temp cannot be an int, use

const char * temp = words[i];

Out of that

  • to use the literal 6 is dangerous, use sizeof to take into account any change on words replacing 6 by sizeof(words)/sizeof(*words)
  • the right type for an index is size_t,
  • to not have always the same executions use srand for instance with the current time

For instance :

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
  const char *words[] = { "one", "two", "three", "four", "five", "six" };
  const size_t nelts = sizeof(words)/sizeof(*words);

  srand(time(NULL));

  for (size_t i=0; i < nelts;  ++i)
  {
    size_t r = (rand() % (nelts - i)) + i;
    const char * temp =  words[i];

    words[i] = words[r];
    words[r] = temp;
  }

  /* show */
  for (size_t i=0; i < nelts;  ++i)
    puts(words[i]);

  return 0;
}

Compilation and executions :

pi@raspberrypi:/tmp $ gcc -pedantic -Wall -Wextra c.c
pi@raspberrypi:/tmp $ ./a.out
four
one
two
five
three
six
pi@raspberrypi:/tmp $ ./a.out
one
three
two
four
five
six
pi@raspberrypi:/tmp $ ./a.out
six
five
two
four
three
one
pi@raspberrypi:/tmp $ ./a.out
three
one
five
four
six
two
bruno
  • 32,421
  • 7
  • 25
  • 37
1

There are multiple errors and flaws in OPs code.

  1. array of strings:
const char *words = { "one", "two", "three", "four", "five", "six" };

Not sure how the compiler reads this (if not complaining). An array of C strings should be:

const char *words[] = { "one", "two", "three", "four", "five", "six" };
  1. magic number
for (int i=0; i<6; i++)

6 is a magic number which is considered as bad style. It's better to give it a name. Even better: the value can be determined by compiler which improves maintainability of code:

int n = sizeof words / sizeof *words;
for (int i = 0; i < n; ++i) {
  1. usage of rand()
int r = (rand() % (6 - i)) + i;

rand() is a pseudo random generator with certain limitations. It shouldn't be used with % n. For certain ns (e.g. 2), this may result into a rather non-random sequence. The cppreference doc. of rand() gives a better example which I turned into a function:

int randomRange(int min, int max)
{
  for (int range = max - min;;) {
    int x = min + rand() / ((RAND_MAX + 1u) / range);
    if (x < max) return x;
  }
}

which is called

int r = randomRange(i, n);
  1. idiomatic swap
int temp =  words[i];

If the type of array elements to swap is const char* the temp must be as well:

    const char *temp = words[i];
    words[i] = words[j];
    words[j] = temp;

The complete sample code:

#include <stdio.h>
#include <stdlib.h>

int randomRange(int min, int max)
{
  for (int range = max - min;;) {
    int x = min + rand() / ((RAND_MAX + 1u) / range);
    if (x < max) return x;
  }
}

int main(void)
{
  /* an array of strings */
  const char *words[] = { "one", "two", "three", "four", "five", "six" };
  /* let compiler determine size */
  int n = sizeof words / sizeof *words;
  /* shuffle */
  for (int i = 0; i < n; ++i) {
    int j = randomRange(i, n);
    /* idiomatic swap */
    const char *temp = words[i];
    words[i] = words[j];
    words[j] = temp;
  }
  /* print result */
  const char *sep = "";
  for (int i = 0; i < n; ++i) {
    printf("%s%s", sep, words[i]);
    sep = ", ";
  }
  /* done */
  return 0;
}

Output:

six, three, one, two, four, five

Live Demo on coliru

Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56
  • @TomKarzes Am I right that `random()` is part of posix standard? I failed to find a reference for `random()` in C standard library (or didn't try hard enough). – Scheff's Cat Jul 07 '19 at 09:10
  • Also, here's the comment about `rand` vs. `random` from the man page for `rand(3)`: Do not use this function in applications intended to be portable when good randomness is needed. (Use random(3) instead.) – Tom Karzes Jul 07 '19 at 09:10
  • I think `random(3)` is part of the Posix standard (not certain). It's defined in ``. I stopped using `rand` ages ago, and use `random` when I need random numbers. – Tom Karzes Jul 07 '19 at 09:12
  • @TomKarzes [random (3)](https://linux.die.net/man/3/random): _Conforming To 4.3BSD, POSIX.1-2001._ It seems so. Nevertheless, for portable code, it's better to not to use `random()` for own functions - agree. – Scheff's Cat Jul 07 '19 at 09:13
  • @TomKarzes cppreference [stdlib.h](https://en.cppreference.com/w/c/numeric/random) does not list it... – Scheff's Cat Jul 07 '19 at 09:17
  • Yes, I think it's standard for Linux and other Unix variants, but not part of the ANSI C library. See [How to generate a random int in C?](https://stackoverflow.com/questions/822323/how-to-generate-a-random-int-in-c) and [random(3) - Linux man page](https://linux.die.net/man/3/random) (I think the second link is the one you posted above). – Tom Karzes Jul 07 '19 at 09:21