int main(void)
{
srand(time(NULL));
char name[10][100] = {
"ali",
"abu",
"kamil",
"sarah",
"siti",
"aina",
"ain",
"hafiz",
"sofea",
"amil"
};
int c, n;
for (c = 1; c <= 5; c++) {
n = rand() % (10 - 1) + 1;
printf("%s\n", name[n]);
}
return 0;
}
每当我运行它时,有两个名称相同。我的讲师说我需要添加额外的代码以避免多余的随机数,但我不知道如何。你能解释一下吗?
答案 0 :(得分:0)
您随意更换名称,这意味着所选名称仍保留在列表中。
如果所需的结果是每次显示一次名称而且只显示一次,那么一旦随机选择该名称,就从该组中删除该名称。
答案 1 :(得分:0)
我想的是:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
unsigned char nameflgs[10] = {0};
srand(time(NULL));
char name[10][100] = {
"ali",
"abu",
"kamil",
"sarah",
"siti",
"aina",
"ain",
"hafiz",
"sofea",
"amil"
};
int c, n;
for (c = 1; c <= 5; c++)
{
for (int l = 0;l < 10;l++)
{
n = rand() % 10;
if (!nameflgs[n])
{
printf("%s\n", name[n]);
nameflgs[n] = 1;
break;
}
}
}
return 0;
}
继续,因为我理解最初的问题Cody ....问题是从列表中打印5个随机名称而不重复名称。即你得到一组名字。所以我添加了一个名字&#39; 10个(最初为零)元素的数组,用作&#39;标记&#39;其中0 =未选择名称,1 =选择名称。两个主要的变化是变量&#39; l&#39;内部的if语句。在内部for循环中,n随机设置一个0-9的数字。然后,以下if语句测试我们的nameflgs数组,看它是否已经输出。如果不输出名称并更新数组以反映这一点,则执行中断以突破内部for循环。下一个名字。再次输入内部for循环,分配n。但是,如果n通过我们已经使用过的nameflgs数组得到一个数字(由我们的if语句测试),那么if的内部主体被跳过,我们回到内部for循环尝试分配另一个n。现在,如果l&gt; 9尝试循环退出(以防止发生无限循环)并且如果c> 5然后循环退出并且程序最终终止。然而,如果原始OP想要所有10个名称(以随机方式)输出,我想我可以添加第二个if如果早期从外部for循环中断(出于效率原因,如果l> 10。)
修改强>
然而,说过我认为我倾向于选择第二个想法:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
srand(time(NULL));
char name[10][100] = {
"ali",
"abu",
"kamil",
"sarah",
"siti",
"aina",
"ain",
"hafiz",
"sofea",
"amil"
};
int nameindxs[10];
//Initialize nameindxs from 0 to 9
for (int n = 0;n < 10;n++)
nameindxs[n] = n;
//Randomly swap nameindxs array going through twice
for (int l = 0;l < 10 * 2;l++)
{
int indx1 = rand() % 10;
int indx2 = rand() % 10;
int tmp = nameindxs[indx1];
nameindxs[indx1] = nameindxs[indx2];
nameindxs[indx2] = tmp;
}
//Output names using nameindxs array
for (int c = 0; c < 5; c++)
{
printf("%s\n", name[nameindxs[c]]);
}
return 0;
}
这次从0-9初始化10个数字的数组。然后通过数组随机交换数字几次。我们应该留下一个相当随机(唯一)的集合。然后最后输出尽可能多的名称,使用我们的nameindxs作为names数组的索引。
答案 2 :(得分:0)
你可能会使它变得比它需要的更难。随机化字符串的一种简单方法是简单地声明指针数组而不是2D数组。这允许您使用简单的“shuffle”,像Fisher-Yates Shuffle一样随机化指针数组以重新排序字符串。这样可以保证您永远不会遇到重复的字符串,并且您可以根据需要重新进行多次重新随机播放,以便重复更改订单。
有很多方法可以实现shuffle。你可以实现一个半泛型的shuffle,它将一个指针数组作为参数并简单地对指针进行洗牌,或者你可以为你的主数组维护第二个整数索引数组,并使用混洗整数作为你的索引对字符串进行洗牌。指针数组(或2D数组)。
以下只是直接实现指针的随机播放。如果必须使用2D数组来保存字符串而不是指针数组,那么只需使用单独的数组。在任何一种情况下,如果您需要输出字符串的某些子集,只需从混洗数组中输出第一个X字符串(或使用混洗索引)。例如:
#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;
}
}
示例使用/输出
$ ./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
仔细看看,如果您有其他问题,请告诉我。
改组问题&amp;答案强>
继续发表评论。如果您有一组要随机播放的内容并维护集合中所有对象之间的关联,那么您应该考虑struct
(结构)。您可以像处理指针到任意的方式一样处理指针到结构数组。回想一下任何系统,指针是一个指针是一个指针。无论指向什么,您都可以处理指针。 (是的,你应该保持他们的指向,但处理指针是一样的。)
下面,为了避免为每个结构的每个成员分配,并避免为每个结构使用固定宽度数组,我使用复合文字为每个问题/答案集创建静态存储,然后只是将地址分配给相同的name
数组。您可以随意提供您喜欢的任何类型的存储和初始化。显然,如果您正在阅读文件中的问题和答案,则需要以不同的方式分配存储空间。
#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;
}
}
示例使用/输出
$ ./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
如果您有任何疑问,请查看并删除评论。本网站上有许多好的问题/答案,涵盖复合文字。