0

0

C++简易抽奖程序怎么做 随机数生成与名单读取

P粉602998670

P粉602998670

发布时间:2025-07-21 11:16:02

|

559人浏览过

|

来源于php中文网

原创

该抽奖程序核心步骤为:1.读取参与者名单;2.使用高质量随机数抽取幸运儿。程序通过库的std::mt19937引擎提升随机性,并以系统时间作为种子确保每次运行结果不同;文件读取时处理空行与编码问题,保障健壮性;同时提供清晰错误提示和交互设计,提升用户体验。

C++简易抽奖程序怎么做 随机数生成与名单读取

一个简单的C++抽奖程序,核心就是两件事:把参与抽奖的人名搞进来,然后用一个靠谱的随机数把幸运儿挑出来。听起来不复杂,实际操作起来,有些小细节值得琢磨,特别是关于随机数的“真”随机性和文件读取的健壮性。

C++简易抽奖程序怎么做 随机数生成与名单读取

解决方案

C++简易抽奖程序怎么做 随机数生成与名单读取
#include 
#include 
#include 
#include 
#include        // 更好的随机数生成器
#include        // 用于生成随机数种子

// 为了提高I/O性能,虽然对小文件不那么关键,但养成习惯总是好的
void setup_fast_io() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);
}

int main() {
    setup_fast_io();

    std::vector participants;
    std::string name;
    const std::string filename = "names.txt"; // 假设名单文件名为names.txt

    std::ifstream infile(filename);
    if (!infile.is_open()) {
        std::cerr << "错误:无法打开名单文件 \"" << filename << "\"。请确保文件存在且可读。\n";
        std::cerr << "每行一个名字,例如:\n";
        std::cerr << "张三\n";
        std::cerr << "李四\n";
        return 1; // 返回非零表示程序异常退出
    }

    // 从文件中读取所有参与者姓名
    while (std::getline(infile, name)) {
        if (!name.empty()) { // 避免空行被添加
            participants.push_back(name);
        }
    }
    infile.close();

    if (participants.empty()) {
        std::cout << "名单里没人,这奖怎么抽?请在 \"" << filename << "\" 文件中添加参与者姓名。\n";
        return 0;
    }

    std::cout << "成功读取 " << participants.size() << " 位参与者。\n";
    std::cout << "正在抽取幸运儿...\n";

    // 使用当前时间作为随机数种子,更可靠的随机性
    // std::mt19937 是一个高质量的伪随机数生成器
    std::mt19937 rng(std::chrono::system_clock::now().time_since_epoch().count());

    // 定义一个均匀分布的整数范围,从0到参与者数量-1
    std::uniform_int_distribution dist(0, participants.size() - 1);

    // 生成随机索引
    int winner_index = dist(rng);

    // 输出中奖者
    std::cout << "\n恭喜!本期幸运儿是: " << participants[winner_index] << "!\n";

    return 0;
}

随机性这东西,到底有多“随机”?

立即学习C++免费学习笔记(深入)”;

说实话,C++里搞随机数,这事儿可比看起来复杂。很多人上来就用 rand()srand(time(NULL)),这在一些简单的、对随机性要求不高的场景下凑合能用。但如果你稍微深入一点,就会发现 rand() 的随机性其实不怎么样,它生成的序列周期短,而且分布可能不够均匀,尤其是在特定编译器或库实现下,问题会更明显。我个人在做一些需要相对“靠谱”随机抽样的项目时,基本都会避开它。

C++简易抽奖程序怎么做 随机数生成与名单读取

在我看来,C++11引入的 库才是正道。它提供了一整套更强大、更灵活的工具,比如 std::mt19937(Mersenne Twister 引擎),这玩意儿生成的伪随机数序列质量高得多,周期也长得惊人。关键在于“伪”这个字,计算机生成的随机数,本质上都是通过一个确定性的算法算出来的,所以它们是“伪”随机。要让它们看起来足够随机,我们就需要一个好的“种子”(seed)。

通常我会用 std::chrono::system_clock::now().time_since_epoch().count() 来作为种子。这基本上就是当前系统时间距离某个固定时刻的纳秒数,每次程序运行,这个值几乎都不一样,所以每次抽奖,抽出的结果也会不同。如果你的程序需要在极短时间内多次运行并保证结果不同,比如毫秒级,那这个时间戳的精度就显得尤为重要。当然,对于一个简易的抽奖程序,这个方法已经绰绰有余了,它能提供足够好的随机分散性,让大家觉得抽奖是公平的。

抽奖名单读起来,总会遇到些奇怪的问题

X Studio
X Studio

网易云音乐·X Studio

下载

读取文件,尤其是在不同操作系统或文本编辑器下,常常会遇到一些让人头疼的小问题。最常见的就是文件路径不对。比如,你把程序编译好了,但 names.txt 文件没放在程序可执行文件的同级目录下,那程序就找不到文件了。这时候 infile.is_open() 就会返回 false,然后程序就报错了。我通常会建议用户把名单文件和程序放在一起,或者在代码里提供一个明确的路径,当然,让用户自己输入路径也是一个不错的选择,但那样代码会稍微复杂一点。

另一个比较隐蔽的问题是文件编码。在Windows上,你可能用记事本保存了一个ANSI编码的文件,但你的C++程序默认可能期望UTF-8编码,或者反过来。结果就是读取出来的中文字符变成乱码,甚至导致读取失败。虽然对于简单的 std::getline 读取单行文本,乱码可能不影响程序逻辑(因为它只关心字符序列),但如果中奖名单里显示的是乱码,那用户体验就太糟糕了。最好的办法是统一使用UTF-8编码保存你的文本文件。

此外,名单文件里可能存在空行。如果直接把空行也 push_backvector 里,那么你的 participants 列表里就会多出一些空字符串,这会影响随机索引的计算,导致可能抽到一个“空白”的幸运儿。所以在代码里加一个 if (!name.empty()) 检查,是个很实用的习惯。处理这些小细节,能让你的程序在实际使用中更加健壮,少出岔子。

程序写好了,怎么让它用起来更顺手、更靠谱?

一个能跑的程序不等于一个好用的程序。对于这个抽奖程序,除了核心功能,还有些地方可以稍微打磨一下,让它更“人性化”。

首先,就是错误提示。当文件找不到或者名单为空的时候,程序不能只是默默地退出或者抛出难以理解的错误信息。像我上面代码里那样,明确告诉用户哪里出了问题,甚至给出解决方案(比如“请确保文件存在且可读”,“每行一个名字”),这能大大降低用户的学习成本和挫败感。

其次,考虑一下用户交互。现在这个程序是跑一次抽一个。如果用户想连续抽好几个,或者想在抽完一个之后再决定是否继续抽,那就需要一个循环和一些简单的用户输入来控制了。比如,在抽完一个之后问一句“是否继续抽取?(y/n)”,这样就灵活多了。当然,对于一个“简易”程序,这可能不是必需的,但往后扩展的时候,这是个不错的方向。

再来,程序的“健壮性”还体现在对边缘情况的处理。例如,如果 names.txt 文件里就只有一个人,那抽奖还有意义吗?程序会正常运行,但结果是唯一的。这虽然不是错误,但你可以在程序启动时提示一下“名单只有一人,抽奖无意义”之类的信息,让用户明白情况。这些看似微不足道的细节,实际上能极大地提升用户对程序的信任感和使用体验。毕竟,一个好的工具,不仅仅是功能完整,更是要让人用起来省心。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

231

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

435

2024.03.01

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

733

2023.08.22

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

197

2023.11.20

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

254

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

206

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1463

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

617

2023.11.24

PHP 表单处理与文件上传安全实战
PHP 表单处理与文件上传安全实战

本专题聚焦 PHP 在表单处理与文件上传场景中的实战与安全问题,系统讲解表单数据获取与校验、XSS 与 CSRF 防护、文件类型与大小限制、上传目录安全配置、恶意文件识别以及常见安全漏洞的防范策略。通过贴近真实业务的案例,帮助学习者掌握 安全、规范地处理用户输入与文件上传的完整开发流程。

1

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7万人学习

Excel 教程
Excel 教程

共162课时 | 11.5万人学习

PHP基础入门课程
PHP基础入门课程

共33课时 | 1.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号