You may be making this harder than it needs to be. One easy way to randomize the strings is simply to declare an array-of-pointers rather than a 2D array. This allows you to use a simple 'shuffle', like a Fisher-Yates Shuffle to randomize the array of pointers to reorder the strings. This guarantees you will never encounter a duplicate string and you are free to re-shuffle as many times as needed to change the order over-and-over again.
There are a number of ways to implement the shuffle. You can implement a semi-generic shuffle that takes an array of pointers as an arguments and simply shuffle the pointers, or you can maintain a second integer array of indexes for your main array and shuffle the strings using the shuffled integers as the indexes for your array of pointers (or 2D array).
The following just implements the shuffle of pointers directly. If you must use a 2D array to hold the strings, instead of an array-of-pointers, then just use a separate array. In either case, if you need to output some subset of the strings, just output the first X-number of strings from the shuffled array (or using the shuffled indexes). For example:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void ptr_shuffle (void *arr, size_t n);
int main (void) {
char *name[] = {"ali", /* array of pointers */
"abu",
"kamil",
"sarah",
"siti",
"aina",
"ain",
"hafiz",
"sofea",
"amil"};
size_t n = sizeof name / sizeof *name;
srand (time (NULL)); /* initialize psuedo-random sequence */
for (size_t i = 0; i < n; i++) /* print original array */
printf ("name[%zu] : %s\n", i, name[i]);
ptr_shuffle (name, n); /* shuffle 'n' pointers in 'name */
printf ("\nshuffled:\n");
for (size_t i = 0; i < n; i++) /* print shuffled array */
printf ("name[%zu] : %s\n", i, name[i]);
return 0;
}
/* shuffle an array of pointers */
void ptr_shuffle (void *arr, size_t n)
{
char *tmp, **a = (char **)arr;
size_t i;
while (n-- > 1) {
i = rand() % (n + 1);
tmp = a[i];
a[i] = a[n];
a[n] = tmp;
}
}
Example Use/Output
$ ./bin/array_ptr_shuffle
name[0] : ali
name[1] : abu
name[2] : kamil
name[3] : sarah
name[4] : siti
name[5] : aina
name[6] : ain
name[7] : hafiz
name[8] : sofea
name[9] : amil
shuffled:
name[0] : siti
name[1] : kamil
name[2] : ali
name[3] : abu
name[4] : aina
name[5] : amil
name[6] : sofea
name[7] : sarah
name[8] : ain
name[9] : hafiz
Look things over and let me know if you have further questions.
Shuffling Questions & Answers
Continuing from your comment. If you have a set of anything which you want to shuffle and maintain the association between all objects in a set, you should be thinking struct
(a structure). You can treat an array-of-pointers-to-struct the same way you treat an array-of-pointers-to-anything. Recall on any system, a pointer-is-a-pointer-is-a-pointer. You can handle pointers generically regardless what they point to. (yes, it is up to you to keep what they point to straight, but dealing with the pointers is the same).
Below, to avoid allocating for each member of each structure, and avoiding using a fixed width array for each, I use a compound literal to create static storage for each question/answer set and then just assign the address to the same name
array. You are free to provide whatever type storage and initialization you like. Obviously, if you are reading the questions and answers from a file, you will need to allocate storage in a different way.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct qa {
char *q, *a1, *a2, *a3;
} qa;
void ptr_shuffle (void *arr, size_t n);
int main (void) {
/* using compound literalts to assign address to name */
qa *name[] = { &(struct qa){ "What is feline?", "dog", "cat", "mouse" },
&(struct qa){ "What is ice?", "Hydrogen", "H20", "water" },
&(struct qa){ "What is k9?", "monkey", "dog", "frog" },
&(struct qa){ "Must I malloc ptrs?", "yes", "no", "depends" }
};
size_t n = sizeof name / sizeof *name;
srand (time (NULL)); /* initialize psuedo-random sequence */
for (size_t i = 0; i < n; i++) /* print original array */
printf ("%s\n\ta) %s\n\tb) %s\n\tc) %s\n",
name[i]->q, name[i]->a1, name[i]->a2, name[i]->a3);
ptr_shuffle (name, n); /* shuffle 'n' pointers in 'name */
printf ("\nshuffled:\n");
for (size_t i = 0; i < n; i++) /* print shuffled array */
printf ("%s\n\ta) %s\n\tb) %s\n\tc) %s\n",
name[i]->q, name[i]->a1, name[i]->a2, name[i]->a3);
return 0;
}
/* shuffle an array of pointers */
void ptr_shuffle (void *arr, size_t n)
{
char *tmp, **a = (char **)arr;
size_t i;
while (n-- > 1) {
i = rand() % (n + 1);
tmp = a[i];
a[i] = a[n];
a[n] = tmp;
}
}
Example Use/Output
$ ./bin/array_ptr_shuffle_struct
What is feline?
a) dog
b) cat
c) mouse
What is ice?
a) Hydrogen
b) H20
c) water
What is k9?
a) monkey
b) dog
c) frog
Must I malloc ptrs?
a) yes
b) no
c) depends
shuffled:
Must I malloc ptrs?
a) yes
b) no
c) depends
What is k9?
a) monkey
b) dog
c) frog
What is feline?
a) dog
b) cat
c) mouse
What is ice?
a) Hydrogen
b) H20
c) water
Look that over and drop a comment if you have questions. There are many good questions/answers on this site that cover compound literals.