百度的一道有关随机数按照指定频率输出的题

该题目要求根据输入文件中指定的概率生成随机字符串。程序首先读取文件,将每个字符串的概率转换为数组,然后通过随机数生成和概率判断来按比例输出字符串。在实现中需要注意输入合法性、概率总和以及非法文件格式的处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


输入:N(整数)

输入:数据文件A.txt,不超过6条记录,字符串长度不超过15个字节
文件格式如下:
字符串\t数字\n

说明:
每行为1条记录;字符串中不含有\t。
数字描述的是该字符串的出现概率,小于等于100的整数。
多条记录的出现概率之和为100,如果A.txt不满足该条件,程序则退出;
如果文件格式错误,程序也退出。

要求:
编写一个程序,输入为N(正整数),读入文件A.txt,按照字符串出现概率随机地输出字符串,输出N条记录

例如:
输入文件A.txt
abc\t20
a\t30
de\t50
输入为:10

即 abc有20%的概率输出,a有30%的概率输出,de有50%的概率输出,输出10条记录
以下为一次输出的结果,多次输出的结果可能不相同。
abc
a
de
de
abc
de
a
de
a
de

题目解析:这个题目其实考察了很多,随机数生成的问题,文件访问的问题,二者中有很多小细节容易让我们忽略的。但是最巧妙的考点是如何按照指定的概率输出。

为此我指定了一个数组number[10],number[i]用于存放字符串i的输出此时,即使用输入的对应频率除以10,就可到了number[i]。我的实现中没有考虑全部的情况,只处理输入频率为10的整数倍。做这种题目的时候,要留心,处理输入不合法,还有总频率和不等于100的情况。

核心步骤是:

1、产生一个随机数 rad;

2、另rad=rad/array_length;array_length为输入的字符串的个数

3、看产number[rad]的值,如果>0,则输出第rad字符串,如果=0.则 rad=(rad+1)%array_length。访问下一个字符串,如果还是为0的话,则继续顺序访问。

4、循环执行步骤3共n次,就得到符合的结果了

程序如下:

#include<cstring>
#include<iostream>
#include <time.h> 
#include <fstream>
using namespace std;

int main()
{
	int n;//表示一共输出多少个数,本例实现中只针对n为10的整数倍的数
	cin >> n;
	char buffer[256];
	ifstream readfile("random.txt");
	if(!readfile){
		cout << "Unable to open readfile";
        exit(1); // terminate with error
		
	}
	char array[10][10];//存放输入的字符串组合
	double number[10]={0,0,0,0,0,0,0,0,0,0};//存放对应字符串的频率

	char a_buf[30];//临时缓冲,存放输入字符串
	int b;	//临时缓冲,存放输入对应字符串的频率,

	int i=0; //用于统计一共多少个字符串
	int sum=0;//用于统计输入的频率,查看最后的频率和是否为1000
	while (! readfile.eof() )
	{
		readfile.getline (buffer,10);
		sscanf(buffer,"%s %d",&a_buf,&b);
		if(a_buf[0] =='@'|| b<=0)
		{ //输入不合法
//			cout <<" The input is error1 "<<endl;
			return 0;
		}

		number[i]=(b/10)*(n/10);//计算每个对应字符串最终输出中输出多少个
		sum+=b;//统计频率和
//		cout << number[i]<<" This is number[i]"<<endl;
		int len=strlen(a_buf);
//		cout << "len is "<<len<<endl;
		for(int j=0; j<len;j++)
			array[i][j]=a_buf[j];
		array[i][j]='\0';//字符串结尾处理
		i++;
		a_buf[0]='@';//缓冲区更新为无实际意义的字符
		b=-1;
	}
	readfile.close();
	
	int array_length=i;//记录一共有多少行输入
	if(sum!=100){//总频率和不为100,则错误,返回
		cout << sum<<endl;
		cout << "The input is error 2:"<<endl;
		return 0;
	}
	
	cout <<"The random result is: "<<endl;
    srand( (unsigned)time( NULL ) );//产生随机数
	for(i=0; i<n;i++){
		int rad = rand();
		rad=rad%array_length;//让随机数控制在0~array_length之内
		while(number[rad]==0)
		{
			rad=((rad+1)%array_length);//如果对应的number次数为0,表示该字符串需要输出的次数已经全部输出,换到下一个字符串
		}
		int length = strlen(array[rad]);
		for(int j=0; j<length;j++)//字符串输出
		{
			cout << array[rad][j];
		}
		cout <<endl;
		number[rad]--;//输出字符串的number次数减1
	}
	return 1;
}


测试数据:

文件里面

a 50
bb 10
ccc 20
dddd 20

终端输入10.

第一次随机结果为:

The random result is:
a
dddd
ccc
ccc
ccc
dddd
dddd
ccc
ccc
bb
Press any key to continue

第二次随机结果为:

10
The random result is:
a
a
a
ccc
dddd
bb
dddd
ccc
a
a
Press any key to continue

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值