如何使用C中的rand()生成0001 - 2000范围内的唯一数字

时间:2018-03-11 03:45:24

标签: c random

我正在尝试生成具有以下两项的数据集:(i)包含从随机生成的值(0001到2000)的学生ID以及(ii)与学生ID(18到30)相对应的年龄。这些随机值保存在各自的数组[1000] 中,如代码

中所示

我遇到了rand()的问题,我已经指定我要为1到2000的学生ID生成随机数,但我遇到了我认为是整数溢出的问题。我认为问题可能来自以下之一:

  • 我的函数是 int 类型,我可能需要尝试不同的类型吗?
  • 我实施 rand()%声明的方式有问题
  • 我不知道的其他一些问题

您可以在输出

中看到我遇到的问题

代码:

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

int createDataSet(void)
{
    srand(time(NULL));             // generates the random numbers

    int i = 0, x, p, count;

    char arrayId[1000];      // array that holds the ID's of 1000 students
    char arrayAges[1000];        // array that holds the ages of 1000 students

    for (count = 0; count < 1000; count++) // Init the "age" and "id" arrays
    {
        arrayId[count] = rand() % 2000 + 1;              // ID range 0001 - 2000
        arrayAges[count] = rand() % (30 + 1 - 18) + 18;   // Age range 18 - 30
    }

    while(i<1000){
        int r=rand() % (2000 + 1 - 0001) + 0001;

        for (x = 0; x < i; x++)
        {
            if(arrayId[x]==r){
                break;
            }
        }
        if(x==i){
            arrayId[i++]=r;
        }
    }

    for (p = 0; p < 1000; p++)
    {
        printf("ID Number: %d       Age: %d\n", arrayId[p], arrayAges[p]);
    }
    return 0;
}

输出:

ID Number: 115       Age: 28
ID Number: 104       Age: 21
ID Number: -113       Age: 25
ID Number: -3       Age: 18
ID Number: -41       Age: 20
ID Number: -94       Age: 28
ID Number: -4       Age: 19
ID Number: 4       Age: 28
ID Number: -112       Age: 23
ID Number: 33       Age: 20
ID Number: -119       Age: 30
ID Number: 12       Age: 23
ID Number: -96       Age: 27
ID Number: -88       Age: 30
ID Number: -105       Age: 20

我的目标是尝试获取数组中的值,如ID号中所示:显示1到2000之间的随机值,并且是无符号类型。任何帮助表示赞赏。谢谢你的时间!

3 个答案:

答案 0 :(得分:1)

虽然您已经对尝试分配和charchar变量范围之外的整数值的初始问题有了一个很好的答案,但仍有大量小问题无法解决

首先,不要在代码中使用幻数。如果您需要常量,可以#define或使用全局enum来定义它们,例如

/* if you need a constants, define them */
enum { MINA = 18, MAXA = 30, MAXS = 1000, MAXID = 2000 };

(其中MINA只是MINIMUMAGE的缩写,MAXS的{​​{1}}等等。)

这样,如果您需要更改范围或限制,您可以在代码顶部放置一个简单的位置来进行更改,而不必选择所有循环限制和变量声明。< / p>

接下来,MAXIMUMSTUDENTS中的return 0;毫无意义。如果您没有返回值,并且您没有在需要返回测量成功/失败的函数中执行任何操作,则将您的函数声明为createDataset。同样,该函数可以生成数据集并将值打印到void,但如果代码的其余部分需要数据集,则无法使用它。为什么?所有数组stdout都被声明为函数的本地数据,并且当函数返回时,它们存储的内存将被销毁(释放以便重用)。您可能希望重构代码以在char arrayId[]..中声明数组,并将数组以及元素数传递给函数进行初始化。

您可以在函数中使用此临时存储,以防止重复ID。您可以简单地声明一个main()长度的字符数组(比如MAXID),初始化为全零,并且在生成每个相应的ID时,将该索引处的值设置为char filled[MAXID] = "";(或一些非零价值)。这使得重复检查成为1

的简单测试

当您考虑重构代码时,您希望将每个函数的功能分成逻辑单元。您的组合生成ID /年龄和输出可能符合您的直接需求,但考虑将生成函数和输出分离为单独的函数。

虽然不是错误,但C的标准编码样式避免使用if (filled[r]) { /* regenerate ID */ }camelCase变量名来支持所有小写,同时保留用于宏和常量的大写名称。这是一个风格问题 - 所以它完全取决于你,但如果不遵循它可能会在某些圈子中产生错误的第一印象。

将这些部分组合在一起,您可以将当前函数重构为单独的生成和打印函数,如下所示:

MixedCase

注意: void createdataset (unsigned short *ids, char *ages, int count) { char filled[MAXID] = {0}; /* array preventing duplicates */ for (count = 0; count < MAXS; count++) /* for each student */ { /* generate an ID */ unsigned short r = (unsigned short)(rand() % MAXID + 1); while (filled[r]) /* while a duplicate, regenerate */ r = (unsigned short)(rand() % MAXID + 1); filled[r] = 1; /* set filled[index] to 1 */ ids[count] = r; /* assign ID to student */ ages[count] = (char)(rand() % (MAXA - MINA + 1) + MINA); } } void prndataset (unsigned short *ids, char *ages, int count) { int i = 0; for (i = 0; i < count; i++) printf ("ID Number: %4hu Age: %2hhd\n", ids[i], ages[i]); } 只应在代码中调用一次。因此,如果您可能生成多个数据集,则应将其放在srand中以确保仅调用一次。

当您开发必须符合特殊条件的代码时,例如main()之间的ID和1-2000之间的年龄,请考虑编写一个简单的验证检查,以验证您的所有值在范围内。例如,您可以执行以下操作:

18-30

(成功时会返回int validateset (unsigned short *ids, char *ages, int count) { int i = 0, err = 0; for (i = 0; i < count; i++) { if (ids[i] < 1 || ids[i] > MAXID) { fprintf (stderr, "error: arrayid[%d] : %hu out of range.\n", i, ids[i]); err = 1; } if (ages[i] < MINA || ages[i] > MAXA) { fprintf (stderr, "error: arrayages[%d] : %hhd out of range.\n", i, ages[i]); err = 1; } } return err; } ,如果在输出任何违规值后有任何值超出范围,则会0

此外,在打印值时,请确保格式说明符与要输出的值类型相匹配。虽然促销规则将使用1short格式说明符处理将较小的值(例如int)转换为%d,但如果您的编译器支持%u修饰符,它们应该用于指定正确的输出尺寸(例如打印h,使用unsigned short或打印%hu,使用unsigned char

在一个简短的示例中将所有部分放在一起,您可以重构代码并添加一个类似于以下内容的验证检查:

%hhu

(通过添加验证检查,您可以放心,如果您的代码在没有显示错误的情况下运行,则数据集已正确生成)

示例使用/输出

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

/* if you need a constants, define them */
enum { MINA = 18, MAXA = 30, MAXS = 1000, MAXID = 2000 };

void createdataset (unsigned short *ids, char *ages, int count)
{
    char filled[MAXID] = {0};           /* array preventing duplicates */

    for (count = 0; count < MAXS; count++)  /* for each student */
    {
        /* generate an ID */
        unsigned short r = (unsigned short)(rand() % MAXID + 1);
        while (filled[r])   /* while a duplicate, regenerate */
            r = (unsigned short)(rand() % MAXID + 1);
        filled[r] = 1;      /* set filled[index] to 1 */
        ids[count] = r;     /* assign ID to student */
        ages[count] = (char)(rand() % (MAXA - MINA + 1) + MINA);
    }
}

void prndataset (unsigned short *ids, char *ages, int count)
{
    int i = 0;

    for (i = 0; i < count; i++)
        printf ("ID Number: %4hu       Age: %2hhd\n", ids[i], ages[i]);
}

int validateset (unsigned short *ids, char *ages, int count)
{
    int i = 0, err = 0;

    for (i = 0; i < count; i++) {
        if (ids[i] < 1 || ids[i] > MAXID) {
            fprintf (stderr, "error: arrayid[%d] : %hu out of range.\n", 
                    i, ids[i]);
            err = 1;
        }
        if (ages[i] < MINA || ages[i] > MAXA) {
            fprintf (stderr, "error: arrayages[%d] : %hhd out of range.\n", 
                    i, ages[i]);
            err = 1;
        }
    }

    return err;
}

int main (void) {

    unsigned short arrayid[MAXS] = {0}; /* size your type to your needed */
    char arrayages[MAXS] = {0};         /* range and enforce the range */

    srand(time(NULL));                  /* initialize random number seed */

    createdataset (arrayid, arrayages, MAXS);   /* initialize dataset */
    if (validateset (arrayid, arrayages, MAXS)) /* validate dataset */
        exit (EXIT_FAILURE);
    prndataset (arrayid, arrayages, MAXS);      /* output dataset */

    return 0;
}

虽然您的主要问题是在$ ./bin/createdataset > dat/dataset1.txt $ head -n 10 dat/dataset1.txt; echo "..."; tail -n 10 dat/dataset1.txt ID Number: 1049 Age: 29 ID Number: 743 Age: 21 ID Number: 915 Age: 22 ID Number: 1539 Age: 19 ID Number: 793 Age: 18 ID Number: 1166 Age: 21 ID Number: 372 Age: 28 ID Number: 1763 Age: 19 ID Number: 782 Age: 20 ID Number: 1490 Age: 30 ... ID Number: 186 Age: 30 ID Number: 1389 Age: 23 ID Number: 1630 Age: 22 ID Number: 432 Age: 27 ID Number: 240 Age: 24 ID Number: 152 Age: 25 ID Number: 1598 Age: 22 ID Number: 1408 Age: 24 ID Number: 834 Age: 24 ID Number: 1699 Age: 25 问题中存储int,但还有许多其他更微妙的问题需要考虑。仔细看看,如果您有任何其他问题,请告诉我。

答案 1 :(得分:0)

arrayId[index]声明为无符号短数组,因为2552000只能存储unsigned short arrayId[1000]; /* try to store negative number, cyclic flow will happen */ unsigned char arrayAges[1000]; soup = BeautifulSoup(r.content,'xml') updates = soup.findAll('body') for update in updates: if not "Next Steps" in update: print (update) else: print "update good" 时不会起作用。但是你想要存储到<body>This is sentence one</body> <body>This is sentence two. Next Steps: Find sentence three.</body> <body>This is sentence three. Next Steps: Find sentence four.</body>

{{1}}

答案 2 :(得分:0)

使用此代码

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

int main(void)
{
    srand(time(NULL));             

    int i = 0, x, p, count;

    unsigned arrayId[1000];   //You Can USE :unsigned int or unsigned short 
    char arrayAges[1000];     

    for (count = 0; count < 1000; count++) 
    {
        arrayId[count] = rand() % 2000 + 1;             
        arrayAges[count] = rand() % (30 + 1 - 18) + 18;  

}

    for (p = 0; p < 1000; p++)
    {
        printf("%d.ID Number: %ld       Age: %d\n",p+1, arrayId[p], arrayAges[p]);
    }
    return 0;
}

输出:

1.ID Number: 1467       Age: 27
2.ID Number: 1316       Age: 21
3.ID Number: 1213       Age: 19
4.ID Number: 171       Age: 29
5.ID Number: 661       Age: 21
6.ID Number: 297       Age: 27
7.ID Number: 853       Age: 23
8.ID Number: 67       Age: 29
9.ID Number: 500       Age: 20
10.ID Number: 274       Age: 24
11.ID Number: 821       Age: 25
12.ID Number: 355       Age: 19
13.ID Number: 1797       Age: 23
14.ID Number: 1036       Age: 30
15.ID Number: 1637       Age: 18
16.ID Number: 385       Age: 22
17.ID Number: 1574       Age: 24
18.ID Number: 1305       Age: 20
19.ID Number: 1658       Age: 24
20.ID Number: 794       Age: 29
21.ID Number: 1758       Age: 24
22.ID Number: 1239       Age: 27
23.ID Number: 989       Age: 30
24.ID Number: 1449       Age: 22
25.ID Number: 1390       Age: 26
26.ID Number: 1731       Age: 25
27.ID Number: 1465       Age: 26
28.ID Number: 792       Age: 20
29.ID Number: 1974       Age: 24
30.ID Number: 1674       Age: 23
31.ID Number: 533       Age: 19
32.ID Number: 1078       Age: 28
33.ID Number: 571       Age: 25
34.ID Number: 48       Age: 20
35.ID Number: 115       Age: 19
36.ID Number: 345       Age: 24
.
.
.

979.ID Number: 35       Age: 30
980.ID Number: 965       Age: 29
981.ID Number: 457       Age: 26
982.ID Number: 615       Age: 24
983.ID Number: 667       Age: 26
984.ID Number: 1381       Age: 19
985.ID Number: 1032       Age: 20
986.ID Number: 534       Age: 26
987.ID Number: 1372       Age: 27
988.ID Number: 1299       Age: 24
989.ID Number: 1463       Age: 24
990.ID Number: 880       Age: 18
991.ID Number: 1928       Age: 28
992.ID Number: 867       Age: 23
993.ID Number: 1580       Age: 29
994.ID Number: 917       Age: 18
995.ID Number: 237       Age: 28
996.ID Number: 384       Age: 19
997.ID Number: 356       Age: 20
998.ID Number: 327       Age: 27
999.ID Number: 1768       Age: 18
1000.ID Number: 148       Age: 27

Process returned 0 (0x0)   execution time : 1.832 s
Press any key to continue.

它也会帮助你

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

int main(void)
{
    srand(time(NULL));             // generates the random numbers

    int i = 0, x, p, count;

     int arrayId[1000];      // array that holds the ID's of 1000 students
    char arrayAges[1000];        // array that holds the ages of 1000 students

    for (count = 0; count < 1000; count++) // Init the "age" and "id" arrays
    {
        //arrayId[count] = rand() % 2000 + 1;              // ID range 0001 - 2000
        arrayId[count] =rand() % (2000 + 1 - 1) + 1;
        arrayAges[count] = rand() % (30 + 1 - 18) + 18;   // Age range 18 - 30
    }

    while(i<1000){
        int r=rand() % (2000 + 1 - 0001) + 0001;

        for (x = 0; x < i; x++)
        {
            if(arrayId[x]==r){
                break;
            }
        }
        if(x==i){
            arrayId[i++]=r;
        }
    }

    for (p = 0; p < 1000; p++)
    {
        printf("%d.ID Number: %ld       Age: %d\n",p+1, arrayId[p], arrayAges[p]);
    }
    return 0;
}