有没有一个函数生成一个随机int数在C?或者我必须使用第三方库?


当前回答

如果你的系统支持arc4random函数族,我建议使用它们来代替标准的rand函数。

arc4random家族包括:

uint32_t arc4random(void)
void arc4random_buf(void *buf, size_t bytes)
uint32_t arc4random_uniform(uint32_t limit)
void arc4random_stir(void)
void arc4random_addrandom(unsigned char *dat, int datlen)

Arc4random返回一个随机的32位无符号整数。

Arc4random_buf将随机内容放在参数buf: void *中。内容的数量由bytes: size_t参数决定。

Arc4random_uniform返回一个随机的32位无符号整数,它遵循规则:0 <= Arc4random_uniform (limit) < limit,其中limit也是一个32位无符号整数。

Arc4random_stir从/dev/urandom读取数据,并将数据传递给arc4random_adrandom以额外随机化它的内部随机数池。

arc4random_adrandom由arc4random_stir使用,根据传递给它的数据填充它的内部随机数池。

如果你没有这些函数,但你在Unix上,那么你可以使用下面的代码:

/* This is C, not C++ */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h> /* exit */
#include <stdio.h> /* printf */

int urandom_fd = -2;

void urandom_init() {
  urandom_fd = open("/dev/urandom", O_RDONLY);

  if (urandom_fd == -1) {
    int errsv = urandom_fd;
    printf("Error opening [/dev/urandom]: %i\n", errsv);
    exit(1);
  }
}

unsigned long urandom() {
  unsigned long buf_impl;
  unsigned long *buf = &buf_impl;

  if (urandom_fd == -2) {
    urandom_init();
  }

  /* Read sizeof(long) bytes (usually 8) into *buf, which points to buf_impl */
  read(urandom_fd, buf, sizeof(long));
  return buf_impl;
}

urandom_init函数打开/dev/urandom设备,并将文件描述符放在urandom_fd中。

urandom函数基本上与rand调用相同,只是更安全,并且它返回一个长(容易更改)。

但是,/dev/urandom可能会有点慢,所以建议您使用它作为不同随机数生成器的种子。

如果您的系统没有/dev/urandom,但是有一个/dev/random或类似的文件,那么您可以简单地将传递的路径更改为在urandom_init中打开。urandom_init和urandom中使用的调用和api(我相信)是POSIX兼容的,因此,即使不是所有POSIX兼容的系统,也应该在大多数系统上工作。

注意:如果可用熵不足,从/dev/urandom读取将不会阻塞,因此在这种情况下生成的值可能是密码不安全的。如果您担心这一点,那么使用/dev/random,如果熵不足,它总是会阻塞。

如果您在另一个系统(即。Windows),然后使用rand或一些内部Windows特定平台依赖的不可移植API。

urandom, rand或arc4random调用的包装器函数:

#define RAND_IMPL /* urandom(see large code block) | rand | arc4random */

int myRandom(int bottom, int top){
    return (RAND_IMPL() % (top - bottom)) + bottom;
}

其他回答

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

//generate number in range [min,max)
int random(int min, int max){
    int number = min + rand() % (max - min);
    return number; 
}

//Driver code
int main(){
    srand(time(NULL));
    for(int i = 1; i <= 10; i++){
        printf("%d\t", random(10, 100));
    }
    return 0;
}

您可以使用悬浮指针的概念。

指向已删除(或释放)内存位置的指针称为悬浮指针。

它将在打印时显示随机值。

试试这个,我把上面已经提到的一些概念放在一起:

/*    
Uses the srand() function to seed the random number generator based on time value,
then returns an integer in the range 1 to max. Call this with random(n) where n is an integer, and you get an integer as a return value.
 */

int random(int max) {
    srand((unsigned) time(NULL));
    return (rand() % max) + 1;
}

我们来看看这个。首先,我们使用srand()函数来为随机化器播种。基本上,计算机可以根据输入给srand()的数字生成随机数。如果你给出相同的种子值,那么每次都会生成相同的随机数。

因此,我们必须用一个总是在变化的值来给随机化器播种。我们通过time()函数将当前时间的值提供给它来实现这一点。

现在,当我们调用rand()时,每次都会产生一个新的随机数。

    #include <stdio.h>

    int random_number(int min_num, int max_num);

    int main(void)
    {
        printf("Min : 1 Max : 40 %d\n", random_number(1,40));
        printf("Min : 100 Max : 1000 %d\n",random_number(100,1000));
        return 0;
    }

    int random_number(int min_num, int max_num)
    {
        int result = 0, low_num = 0, hi_num = 0;

        if (min_num < max_num)
        {
            low_num = min_num;
            hi_num = max_num + 1; // include max_num in output
        } else {
            low_num = max_num + 1; // include max_num in output
            hi_num = min_num;
        }

        srand(time(NULL));
        result = (rand() % (hi_num - low_num)) + low_num;
        return result;
    }

对于Linux C应用程序:

这是我根据上面的答案重新编写的代码,它遵循我的C代码实践并返回任意大小的随机缓冲区(具有适当的返回代码等)。确保在程序开始时调用urandom_open()一次。

int gUrandomFd = -1;

int urandom_open(void)
{
    if (gUrandomFd == -1) {
        gUrandomFd = open("/dev/urandom", O_RDONLY);
    }

    if (gUrandomFd == -1) {
        fprintf(stderr, "Error opening /dev/urandom: errno [%d], strerrer [%s]\n",
                  errno, strerror(errno));
        return -1;
    } else {
        return 0;
    }
}


void urandom_close(void)
{
    close(gUrandomFd);
    gUrandomFd = -1;
}


//
// This link essentially validates the merits of /dev/urandom:
// http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/
//
int getRandomBuffer(uint8_t *buf, int size)
{
    int ret = 0; // Return value

    if (gUrandomFd == -1) {
        fprintf(stderr, "Urandom (/dev/urandom) file not open\n");
        return -1;
    }

    ret = read(gUrandomFd, buf, size);

    if (ret != size) {
        fprintf(stderr, "Only read [%d] bytes, expected [%d]\n",
                 ret, size);
        return -1;
    } else {
        return 0;
    }
}