c语言生成随机数
本帖最后由 mxwawaawxm 于 2021-7-14 22:05 编辑# 功能需求
挺无聊的功能,而且自己代码写得太杂乱了
用户编辑配置文件random_config.ini里的参数,如随机数的最小值和最大值、生成随机数的个数、不生成的随机数
读取random_config.ini里参数的值,并生成不重复的随机数
# 源代码
```c
/*
1、尝试读取配置文件random_config.ini的信息
失败,说明缺少配置文件
成功,读取配置文件里的min_num、max_num、times
定义标志数组int flags,依次存放是否正确读取参数值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 = {0};
// 不生成的数字序列数组,最多20个
int blacklist_num;
// 不生成的数字序列数组有效个数
int blacklist_num_real=0;
// 不生成的数字序列字符串
char blacklist_num_str;
// 文件存在
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里编辑参数的值
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)
我写的 检测随机数是否有效,是检测两方面,检测随机数会否跟生成的数字重复以及随机数会否跟 不需要的数字 相同 c03xp 发表于 2021-7-13 10:52
既然用到ini格式了,就没必要自己解析了。使用GetProfileString系列
查了下,是不是应该用GetPrivateProfileInt、GetPrivateProfileString函数
而且ini格式里,还能写注释吗
而且是不是要得严格按这样的格式写ini文件
key=name
谢谢楼主分享!支持! 学习了,这个我们也研究过 不错,想过几次没有思路 这么复杂
c#语言
Random n1 = new Random();
string ran = (n1.Next(100000, 900000) * DateTime.Now.Millisecond + 99999).ToString().Substring(0, 6);
2句代码搞定 本帖最后由 mxwawaawxm 于 2021-6-28 18:43 编辑
我前面是写了功能需求的,不全是生成随机数@ajm3
用户编辑配置文件random_config.ini里的参数,如随机数的最小值和最大值、生成随机数的个数、不生成的随机数
读取random_config.ini里参数的值,并生成不重复的随机数
https://attach.52pojie.cn/forum/202106/21/155659vjv6w155qql11066.png zjtwxws 发表于 2021-6-27 19:19
编译有错,请问有人遇到问题了吗?
gcc编译没问题
gcc -Wall "text.c" -finput-charset=UTF-8 -fexec-charset=GBK -o "1.exe" srand( time(0) );//为生成随机数种种子,可以产生不同的随机数
用这个他不香吗,搞那复杂干嘛
页:
[1]
2