我一直在尝试制作一个由极不同的随机整数组成的数组,其中25个介于1到75之间。已经陷入无限循环。非常感谢!
我试图寻找解决方案,但我要么不理解它们,要么就没有找到适合我水平的东西。 顺便说一句,我确保我使用了srand(time(NULL));for (i = 0; i < 25; i++)
{
while (k != 1)
{
arr[i] = rand() % 75 + 1;
for (j = 0; j < 25; j++)
{
if (arr[i] == arr[j])
{
k++;
}
}
}
k = 0;
}
整个代码:
/*********************************
* Class: MAGSHIMIM C2 *
* Week: *
* Name: *
* Credits: *
**********************************/
#include <stdio.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main(void)
{
srand(time(NULL));
int i = 0;
int j = 0;
int k = 0;
int arr[25] = { 0 };
for (i = 0; i < 25; i++)
{
while (k != 1)
{
arr[i] = rand() % 75 + 1;
for (j = 0; j < 25; j++)
{
if (arr[i] == arr[j])
{
k++;
}
}
}
k = 0;
}
for (i = 0; i < 25; i++)
{
printf("%d", arr[i]);
}
getchar();
return 0;
}
expecetd:一个不错的差分数组,但是我遇到了无限循环。
答案 0 :(得分:1)
一种方法是在所需范围内制造一个池或一包数字,然后从中选择。重复检查以查看是否已选择号码并不困难,并且效率更高。您修改后的程序现在为:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define ARRLEN 25 // how many to pick
#define NUMBERS 75 // range of available numbers
#if NUMBERS < ARRLEN // precaution
#error Impossible job!
#endif
int cmp(const void *a, const void *b)
// optional, for qsort
{
return *(int *)a - *(int *)b;
}
int main(void)
{
int arr[ARRLEN]; // final array
int bag[NUMBERS]; // bag of available numbers
int avail = NUMBERS; // size of bag available
srand((unsigned)time(NULL));
// prepare the bag of available numbers
for(int i = 0; i < NUMBERS; i++) {
bag[i] = i + 1;
}
// fill the array with values from the bag
for(int i = 0; i < ARRLEN; i++) {
int index = rand() % avail; // random index into array
arr[i] = bag[index]; // take that number
avail--;
bag[index] = bag[avail]; // replace with the one from the top
}
// just to check, sort the array, can be deleted
qsort(arr, ARRLEN, sizeof arr[0], cmp);
// output the result
for (int i = 0; i < ARRLEN; i++) {
printf("%d ", arr[i]);
}
printf("\n");
getchar();
return 0;
}
我对数组进行了排序,以使其易于查看是否存在重复项。可以删除qsort
行和cmp
函数。
三个运行的程序输出
6 7 8 9 12 16 17 19 21 27 31 35 43 46 47 50 51 53 59 64 65 66 70 71 72 2 6 7 14 17 23 24 25 30 31 32 34 36 37 45 58 59 61 65 68 69 71 73 74 75 5 10 13 18 20 21 25 30 34 36 39 40 41 43 49 50 54 58 60 63 64 66 67 72 75
答案 1 :(得分:0)
...但是我遇到了无限循环。
只需替换
while (k != 1)
{
arr[i] = rand() % 75 + 1;
for (j = 0; j < 25; j++) {
...
}
}
k = 0;
作者
do
{
k = 0;
arr[i] = rand() % 75 + 1;
for (j = 0; j < 25; j++) {
...
}
} while (k != 1);
请注意,检查所有数组(包括未由随机值设置的条目)也是没有用的,因此可以是:
do
{
k = 0;
arr[i] = rand() % 75 + 1;
for (j = 0; j < i; j++)
{
if (arr[i] == arr[j])
{
k++;
}
}
} while (k != 0);
因为现在 j 无法将 i 赋值,所以测试是(k != 0)
而不是(k != 1)
或更好,因为当找到相同的值时,没有理由继续
do
{
arr[i] = rand() % 75 + 1;
for (j = 0; j < i; j++)
{
if (arr[i] == arr[j])
break;
}
} while (j != i);
要清楚地看到这些值,还应在它们之间添加一个空格并添加最后一个换行符:
for (i = 0; i < 25; i++)
{
printf("%d ", arr[i]);
}
putchar('\n');
这些更改,编译和执行之后:
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -Wall r.c
pi@raspberrypi:/tmp $ ./a.out
74 60 16 65 54 19 55 45 41 24 39 59 66 36 27 22 68 49 29 14 28 5 71 56 72
pi@raspberrypi:/tmp $ ./a.out
16 34 62 29 74 41 3 43 69 17 61 22 28 59 7 65 5 46 60 20 66 14 49 54 45
pi@raspberrypi:/tmp $
修改
实现很简单,但是以这种方式查找尚未使用的值可能会花费一些时间,并且允许值的范围越接近返回值的数量,所需的时间就越长。因此,与允许的值范围相比,当返回的值很少时,这种解决方案是很好的。
关于风向标的有趣提议则相反,对 rand 的调用次数仅等于要返回的值的数量,但是允许值的范围越大,则值越大数组 bag 很大,可能会溢出内存大小。
对于25个从1到75的值来说,Weather Vane的解决方案更好。。。甚至我的提议似乎只需要0.001秒就可以覆盖我的树莓派了,所以几乎什么都没有
答案 2 :(得分:0)
int *fillint(int *arr, size_t size)
{
int added = 0;
int pos = 0
while(pos != size)
{
int rv;
do
{
added = 1;
rv = rand();
for(size_t index = 0; index < pos; index++)
{
if(arr[index] == rv)
{
added = 0;
break;
}
}
}while(!added)
arr[pos++] = rv;
}
return arr;
}
答案 3 :(得分:0)
Weather Vane的 bag 方法的另一个细微变化,不是准备一个包含所有可用数字的袋子,而是简单地声明一个数组,该数组的最大元素数等于对所有对象初始化的可接受数字范围零(例如int arr[75] = {0};
)。无需填充数组,每次使用该数字填充数组时,您只需将元素增加1。
要确保仅使用唯一数字,请检查数组的相应元素是否为零,如果为零,请使用该数字并递增该元素。如果它不是零,则说明该数字已被使用-请生成另一个数字,然后重试。
例如,将数组的整数个数为25
,将任何一个整数的最大值为75
,您可以这样做:
#define NINT 25
#define MAXI 75
...
int arr[NINT],
seen[MAXI] = {0};
...
for (int i = 0; i < NINT; i++) { /* for each needed element */
int tmp = rand() % MAXI + 1; /* generate a random in range */
while (seen[tmp-1]) /* has been seen/used yet? */
tmp = rand() % MAXI + 1; /* if so, generate another */
seen[tmp-1]++; /* incement element */
arr[i] = tmp; /* assign unique value to arr */
}
(注意:seen
索引被映射为tmp-1
以映射到有效索引0-74
,而为tmp
生成的数字将是1-75
使用rand() % MAXI + 1
。您可以容纳这种类型的映射所需的任何范围,使用1000001 - 1000075
中的数字范围仍然只需要包含75个元素的seen
数组。 )
要输出按顺序使用的数字,只需要输出与seen
数组(+1
的每个非零元素相对应的索引(1-75
即可映射回{{1} }值范围),例如
for (int i = 0; i < MAXI; i++)
if (seen[i])
printf (" %d", i + 1);
putchar ('\n');
将其完全放在一个简短的示例中,您可以这样做:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NINT 25
#define MAXI 75
int main (void) {
int arr[NINT],
seen[MAXI] = {0};
srand (time(NULL));
for (int i = 0; i < NINT; i++) { /* for each needed element */
int tmp = rand() % MAXI + 1; /* generate a random in range */
while (seen[tmp-1]) /* has been seen/used yet? */
tmp = rand() % MAXI + 1; /* if so, generate another */
seen[tmp-1]++; /* incement element */
arr[i] = tmp; /* assign unique value to arr */
}
puts ("array:");
for (int i = 0; i < NINT; i++) {
if (i && i % 5 == 0)
putchar ('\n');
printf (" %2d", arr[i]);
}
puts ("\n\nused:");
for (int i = 0; i < MAXI; i++)
if (seen[i])
printf (" %d", i + 1);
putchar ('\n');
}
(注意:显然,可见数组的大小将限制为可用的堆栈大小,因此,如果所需数字范围超出了用seen可用的内存, >自动存储类型,则需要将seen
设置为具有已分配存储类型的数组。
使用/输出示例
$ ./bin/randarr25-75
array:
1 18 70 26 75
29 31 58 22 9
5 13 3 25 35
40 48 44 57 56
60 50 71 67 43
used:
1 3 5 9 13 18 22 25 26 29 31 35 40 43 44 48 50 56 57 58 60 67 70 71 75
无论您使用袋子还是数组来跟踪看到的数字,结果都是相同的。没有人比另一个更好。将它们都添加到您的C工具箱中。
答案 4 :(得分:-1)
在内部for循环中,对j进行迭代,直到j
此外,每次检查以前的出现次数时,请将k的值初始化为零,这使代码更易于阅读。
如果发现一个事件,只需中断一下,即使使较大的值有所不同,它也可使算法运行得更快。
类似这样的东西:
for (i = 0; i < 25; i++)
{
k = 1;
while (k != 0)
{
arr[i] = rand() % 75 + 1;
k = 0;
for (j = 0; j < i; j++)
{
if (arr[i] == arr[j])
{
k++;
break;
}
}
}
}