吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2400|回复: 17
收起左侧

[其他转载] c语言生成随机数

[复制链接]
mxwawaawxm 发表于 2021-6-21 15:53
本帖最后由 mxwawaawxm 于 2021-7-14 22:05 编辑

功能需求

挺无聊的功能,而且自己代码写得太杂乱了
用户编辑配置文件random_config.ini里的参数,如随机数的最小值和最大值、生成随机数的个数、不生成的随机数
2021-06-21_155535.png
读取random_config.ini里参数的值,并生成不重复的随机数

源代码

/*
1、尝试读取配置文件random_config.ini的信息
    失败,说明缺少配置文件
    成功,读取配置文件里的min_num、max_num、times
            定义标志数组int flags[4],依次存放是否正确读取参数值min_num、max_num、times、blacklist_num的标志
            只有正确读取min_num,才尝试读取max_num。其余一样

            读取blacklist_num
                先存储进字符串blacklist_num_str
                再切分转化成数字,存储进数组blacklist_num
                同时统计数组blacklist_num元素的个数

2、依据min_num、max_num、times、blacklist_num,生成随机数
    检查min_num会否大于max_num
    检查times会否超过min_num和max_num的差值
        确保随机数不重复
        确保随机数不是blacklist_num的数字
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

#define CONFIG "random_config.ini"
#define MIN_NUM "min_num"
#define MAX_NUM "max_num"
#define TIMES "times"
#define BLACKLIST_NUM "blacklist_num"
#define BLACKLIST_LEN 20
#define BLACKLIST_STR_LEN 100

int file_exist(const char *file_name);
void read_info(const char *file_name, int *min_num, int *max_num, int *times, char *blacklist_num_str, int *flags);
void read_info_num(FILE *fp, const char *info, int *num_info, int *flag);
void read_info_blacklist(FILE *fp, const char *info, char *blacklist_num_str, int *flag);
void split_blacklist_num_str(char *blacklist_num_str, int *blacklist_num, int *blacklist_num_real);
void print_blacklist_num(int *blacklist_num, int blacklist_num_real);
void generate_rand_num(int min_num, int max_num, int times, int *blacklist_num, int blacklist_num_real);
void chk_num(int num, int *rand_num_array, int *idx, int *blacklist_num, int blacklist_num_real);
void ignore_comment(FILE *fp);

int main(int argc, const char *argv[])
{
    // 可能的最小数字、最大数字、最多生成多少个数字
    int min_num, max_num, times;
    // 存放读取min_num、max_num、times、blacklist_num的标志
    int flags[4] = {0};
    // 不生成的数字序列数组,最多20个
    int blacklist_num[BLACKLIST_LEN];
    // 不生成的数字序列数组有效个数
    int blacklist_num_real=0;
    // 不生成的数字序列字符串
    char blacklist_num_str[BLACKLIST_STR_LEN];

    // 文件存在
    if (file_exist(CONFIG)==0) {
        // 读取配置文件信息
        read_info(CONFIG, &min_num, &max_num, ×, blacklist_num_str, flags);
        // 把字符串blacklist_num_str依次切分,并转化为数字
        // 并存储进数组blacklist_num
        split_blacklist_num_str(blacklist_num_str, blacklist_num, &blacklist_num_real);

        // 打印转化成数字后的数组blacklist_num,测试用途,非必需
        // print_blacklist_num(blacklist_num, blacklist_num_real);

        // 检查min_num、max_num、times是否正确读取
        if ((*flags) * *(flags+1) * *(flags+2)==1) {
            generate_rand_num(min_num, max_num, times, blacklist_num, blacklist_num_real);
        }
    } else {
        printf("%s%s", CONFIG, "不存在");
    }

    return 0;
}

/* 判断配置文件是否存在 */
int file_exist(const char *file_name)
{
    // F_OK=0,文件存在
    return access(file_name, F_OK);
}

/* 读取配置文件信息 */
void read_info(const char *file_name, int *min_num, int *max_num, int *times, char *blacklist_num_str, int *flags)
{
    FILE *fp = fopen(file_name, "r");

    if (fp==NULL) {
        printf("读取配置%s文件失败\n", file_name);
    } else {
        // 读取随机数可能的最小数字min_num
        read_info_num(fp, MIN_NUM, min_num, flags);

        if (*flags==1) {
            // 读取随机数可能的最大数字max_num
            read_info_num(fp, MAX_NUM, max_num, flags+1);
        }

        if (*(flags+1)==1) {
            // 读取随机数最多生成多少个数字times
            read_info_num(fp, TIMES, times, flags+2);
        }

        if (*(flags+2)==1) {
            // 读取随机数不生成的数字
            // 并存储进字符串blacklist_num_str
            read_info_blacklist(fp, BLACKLIST_NUM, blacklist_num_str, flags+3);
        }
    }

    fclose(fp);
}

/* 跳过ini配置文件的注释 */
void ignore_comment(FILE *fp)
{
    int character = fgetc(fp);

    while (!feof(fp) && (character==';' || character!='\n')) {
        character = fgetc(fp);
    }        
}

/* 读取配置文件里min_num、max_num、times */
void read_info_num(FILE *fp, const char *info, int *num_info, int *flag)
{
    // =%d\n\0,总共5个字符
    char *format_char = (char *)malloc((strlen(info)+5)*sizeof(char));
    // 生成格式化字符串
    sprintf(format_char, "%s=%%d\n", info);
    // printf("%s\n", format_char);

    // 跳过ini配置文件的注释
    ignore_comment(fp);
    if ((fscanf(fp, format_char, num_info))==1) {
        printf(format_char, *num_info);
        *flag = 1;
    } else {
        printf("读取%s出错,请检查参数值是否填写错误\n", info);
    }
    // 清空缓存
    fflush(stdin);
    fflush(stdout); 
    // 释放动态分配的内存空间
    free(format_char);  
}

/* 读取配置文件里参数blacklist_num
   并存储进字符串blacklist_num_str */
void read_info_blacklist(FILE *fp, const char *info, char *blacklist_num_str, int *flag)
{
    // =%d\n\0,总共5个字符
    char *format_char = (char *)malloc((strlen(info)+5)*sizeof(char));
    // 生成格式化字符串
    sprintf(format_char, "%s=", info);
    // printf("%s\n", format_char);

    // 跳过ini配置文件的注释
    ignore_comment(fp);
    // 读取掉前面的参数blacklist_num=
    fscanf(fp, format_char);

    if ((fgets(blacklist_num_str, BLACKLIST_STR_LEN, fp))!=NULL) {
        printf("%s%s\n", format_char, blacklist_num_str);
        // printf(format_char, blacklist_num_str);
        *flag = 1;
    } else {
        printf("读取%s出错,参数数值可能为空或者填写错误\n", info);
    }
    // 清空缓存
    fflush(stdin);
    fflush(stdout); 
    // 释放动态分配的内存空间
    free(format_char); 
}

/* 把字符串blacklist_num_str依次切分,并转化为数字
   并存储进数组blacklist_num */
void split_blacklist_num_str(char *blacklist_num_str, int *blacklist_num, int *blacklist_num_real)
{
    const char *delim = ", /n";
    char *saveptr = NULL;
    char *token;

    token = strtok_s(blacklist_num_str, delim, &saveptr);

    while (token!=NULL && *blacklist_num_real<BLACKLIST_LEN) {
        // printf("%s\n", token);
        *(blacklist_num++) = atoi(token);
        (*blacklist_num_real)++;
        token = strtok_r(NULL, delim, &saveptr); 
    }
}

/* 打印转化成数字后的数组blacklist_num,测试用途,非必需 */
void print_blacklist_num(int *blacklist_num, int blacklist_num_real)
{
    for (int i=0;i<blacklist_num_real;i++) {
        printf("%d ", *(blacklist_num+i));
    }
    printf("\n");
}

/* 生成随机数 */
void generate_rand_num(int min_num, int max_num, int times, int *blacklist_num, int blacklist_num_real)
{
    srand(time(NULL));

    // 检查min_num会否大于max_num
    if (min_num>max_num) {
        fprintf(stdout, "随机数的最小值大于最大值,请检查配置文件参数值是否正确\n");
    // 检查times会否超过min_num和max_num的差值
    } else if (times>=max_num-min_num) {
        fprintf(stdout, "生成数字的个数超过最大值和最小值的差值\n");
    } else {
        int idx, num;
        // printf("%d\n", times);
        int *rand_num_array = (int *)malloc(sizeof(int)*times);

        printf("\n\n==========================================\n生成的随机数是\n");
        for (idx=0;idx<times;) {
            num = rand()%(max_num-min_num+1)+min_num;
            chk_num(num, rand_num_array, &idx, blacklist_num, blacklist_num_real);
        }
        for (idx=0;idx<times;idx++) {
            printf("%d\n", *(rand_num_array+idx));
        }
        printf("==========================================\n");
        free(rand_num_array);
    }
}

/* 检查随机数是否有效 */
void chk_num(int num, int *rand_num_array, int *idx, int *blacklist_num, int blacklist_num_real)
{
    int i, flag_dup=1, flag_blacklist=1;

    // 检查生成的随机数是否重复
    for (i=0;i<*idx;i++) {
        if (num==*(rand_num_array+i)) {
            flag_dup=0;
            break;
        }
    }

    // 检查生成的随机数是否是黑名单数字
    if (flag_dup==1) {
        for (i=0;i<blacklist_num_real;i++) {
            if (num==*(blacklist_num+i)) {
                flag_blacklist=0;
                break;
            }
        }
    }

    // 随机数有效,存入rand_num_array,并将索引递增
    if (flag_dup==1 && flag_blacklist==1) {
        *(rand_num_array+*idx) = num;
        (*idx)++;
    }
}

编译后的文件



打开后运行cmd文件,需要编辑参数,就在random_config.ini里编辑参数的值

random.zip (19.9 KB, 下载次数: 23)

2021-06-21_155119.png

免费评分

参与人数 4吾爱币 +10 热心值 +3 收起 理由
Mrjtb + 1 + 1 谢谢@Thanks!
fgfghtf + 1 + 1 我很赞同!
苏紫方璇 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
ghimi + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| mxwawaawxm 发表于 2021-7-10 06:40
xub66sh 发表于 2021-7-9 15:24
你用srand(time(0))函数避免随机数重复,然后求模运算%68+1,结果跟你不需要的数字对比,一样的话重新 ...

/* 检查随机数是否有效 */
void chk_num(int num, int *rand_num_array, int *idx, int *blacklist_num, int blacklist_num_real)

我写的 检测随机数是否有效,是检测两方面,检测随机数会否跟生成的数字重复以及随机数会否跟 不需要的数字 相同
 楼主| mxwawaawxm 发表于 2021-7-14 21:31
c03xp 发表于 2021-7-13 10:52
既然用到ini格式了,就没必要自己解析了。使用GetProfileString系列

查了下,是不是应该用GetPrivateProfileInt、GetPrivateProfileString函数
而且ini格式里,还能写注释吗
而且是不是要得严格按这样的格式写ini文件
[section]
key=name

sergin 发表于 2021-6-21 19:02
nappywu 发表于 2021-6-23 15:23
学习了,这个我们也研究过
intel286 发表于 2021-6-24 06:14
不错,想过几次没有思路
头像被屏蔽
zjtwxws 发表于 2021-6-27 18:47
提示: 作者被禁止或删除 内容自动屏蔽
头像被屏蔽
zjtwxws 发表于 2021-6-27 19:19
提示: 作者被禁止或删除 内容自动屏蔽
ajm3 发表于 2021-6-28 09:38
这么复杂
c#语言
[Asm] 纯文本查看 复制代码
 Random n1 = new Random();
                string ran = (n1.Next(100000, 900000) * DateTime.Now.Millisecond + 99999).ToString().Substring(0, 6);

2句代码搞定
 楼主| mxwawaawxm 发表于 2021-6-28 18:41
本帖最后由 mxwawaawxm 于 2021-6-28 18:43 编辑

我前面是写了功能需求的,不全是生成随机数@ajm3
[Asm] 纯文本查看 复制代码
用户编辑配置文件random_config.ini里的参数,如随机数的最小值和最大值、生成随机数的个数、不生成的随机数
读取random_config.ini里参数的值,并生成不重复的随机数

 楼主| mxwawaawxm 发表于 2021-6-30 10:34
zjtwxws 发表于 2021-6-27 19:19
编译有错,请问有人遇到问题了吗?

gcc编译没问题
gcc -Wall "text.c" -finput-charset=UTF-8 -fexec-charset=GBK -o "1.exe"
zouyingsheng 发表于 2021-7-3 10:36
        srand( time(0) );  //为生成随机数种种子,可以产生不同的随机数
用这个他不香吗,搞那复杂干嘛
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 14:59

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表