【黑马程序员】STL实战--演讲比赛管理系统

文章目录

  • 演讲比赛管理系统
    • 需求说明
      • 比赛规则
      • 程序功能
    • 创建管理类
      • 功能描述
      • 创建演讲比赛管理类
    • 菜单功能
      • 添加菜单成员函数声明
      • 菜单成员函数实现
      • 菜单功能测试
    • 退出功能
      • 添加退出功能声明
      • 退出成员函数实现
      • 退出功能测试
    • 演讲比赛功能
      • 功能分析
      • 创建选手类
      • 比赛
        • 成员属性添加
        • 初始化属性
        • 创建选手
        • 开始比赛成员函数
        • 抽签
        • 比赛过程
        • 显示晋级选手信息
        • 第二轮比赛
        • 保存分数
      • 查看记录
        • 从文件中加载记录
        • 将加载的记录进行展示
        • 功能实现
      • 清空记录

演讲比赛管理系统

需求说明

比赛规则

在这里插入图片描述

程序功能

在这里插入图片描述

创建管理类

功能描述

  • 提供菜单界面与用户交互

  • 对演讲比赛流程进行控制

  • 与文件的读写交互

创建演讲比赛管理类

  • 新建speechManager.hpp
#pragma once#include <iostream>using namespace std;// 设计演讲比赛类
class SpeechManager {
public:// 构造函数    SpeechManager();// 析构函数   ~SpeechManager();
};
  • 新建speechManager.cpp
#include "speechManager.h"// 构造函数
SpeechManager::SpeechManager() {}// 析构函数
SpeechManager::~SpeechManager() {}

菜单功能

  • 功能描述:与用户的交互界面

添加菜单成员函数声明

  • speechManager.hpp中添加展示菜单成员函数声明
    // 菜单功能void showMenu();

菜单成员函数实现

  • speechManager.cpp中实现成员函数
// 菜单功能
void SpeechManager::showMenu() {cout << "*************************************" << endl;cout << "*******欢迎使用演讲比赛管理系统******" << endl;cout << "************1.开始演讲比较***********" << endl;cout << "************2.查看往届记录***********" << endl;cout << "************3.情况比赛记录***********" << endl;cout << "************4.退出比赛程序***********" << endl;cout << "*************************************" << endl;
}

菜单功能测试

  • 菜单功能测试,新建main.cpp
#include "speechManager.hpp"int main() {SpeechManager sm;sm.showMenu();
}
  • 运行结果

在这里插入图片描述

退出功能

添加退出功能声明

  • speechManager.hpp中添加退出成员函数声明
    // 退出功能void Logout();

退出成员函数实现

  • speechManager.cpp中实现退出成员函数
// 退出功能
void SpeechManager::Logout() {cout << "即将退出系统,再见" << endl;exit(0);
}

退出功能测试

  • 退出功能测试,在main.cpp
#include "speechManager.hpp"int main() {int choice;SpeechManager sm;while (true) {sm.showMenu();cout << "请输入你要使用的功能" << endl;cin >> choice;switch (choice) {case 1: //1.开始演讲比较break;case 2: //2.查看往届记录break;case 3: //3.清空比赛记录break;case 4: //4.退出比赛程序sm.Logout();break;}}
}
  • 运行结果

在这里插入图片描述

演讲比赛功能

功能分析

  • 比赛流程分析

    • 抽签–>开始演讲比赛–>显示第一轮比赛结果

    • 抽签–>开始演讲比赛–>显示前三名结果–>保存分数

创建选手类

  • 选手类中包括属性:选手姓名、分数

  • 新建speaker.hpp

#pragma once#include <iostream>
#include <string>using namespace std;// 选手类
class Speaker {
public:string name;        // 姓名double score[2];    // 最多有两轮分数
};

比赛

成员属性添加
  • speechManager.hpp中添加
#include <vector>
#include <map>
#include "speaker.hpp"// 类成员属性添加// 比赛选手容器 12人vector<int> v1;// 第一轮晋级选手容器 6人vector<int> v2;// 前三名容器 3人vector<int> v3;// 存放编号,以及队形的具体选手容器map<int, Speaker> mSpeaker;// 记录比赛轮数int mIndex;
初始化属性
  • speechManager.hpp中添加初始化属性成员函数声明
    // 初始化成员属性void initSpeech();
  • speechManager.cpp中实现初始化属性成员函数,并在构造函数中调用
// 初始化成员属性
void SpeechManager::initSpeech() {// 初始确保容器为空this->v1.clear();this->v2.clear();this->v3.clear();this->mSpeaker.clear();// 初始比赛轮数this->mIndex = 1;
}
创建选手
  • speechManager.hpp中添加创建选手成员函数声明
    // 创建选手void createSpeaker();
  • speechManager.cpp中实现创建选手成员函数,并在构造函数中调用
// 创建选手
void SpeechManager::createSpeaker() {string nameSeed = "ABCDEFGHIJKL";for (int i = 0; i < nameSeed.size(); i++) {string name = "选手";name += nameSeed[i];Speaker sp;sp.name = name;for (int i = 0; i < 2; i++) {sp.score[i] = 0;}// 12名选手编号this->v1.push_back(i + 10001);// 将选手放入到map中this->mSpeaker.insert(make_pair(i + 10001, sp));}
}
  • 创建成员测试
#include "speechManager.hpp"
#include "speaker.hpp"int main() {SpeechManager sm;for (map<int, Speaker>::iterator it = sm.mSpeaker.begin(); it != sm.mSpeaker.end(); it++) {cout << it->first << "\t" << (it->second).name << "\t" << (it->second).score[0] << "\t" << (it->second).score[1]<< endl;}
}
  • 运行结果

在这里插入图片描述

开始比赛成员函数
  • speechManager.hpp中添加开始比赛函数声明
    // 开始比赛void startSpeech();
  • speechManager.cpp中实现初始化属性成员函数,在开始比赛实现中先定义整体比赛的流程在慢慢实现,开始比赛功能在菜单中用户选择开始比赛时调用
// 开始比赛
void SpeechManager::startSpeech() {// 第一轮比赛// 1.抽签// 2.比赛// 3.显示晋级结果// 第二轮比赛// 1.抽签// 2.比赛// 3.显示最终结果// 4.保存分数
}
抽签
  • 抽签的本质就是打乱参赛者

  • speechManager.hpp中添加抽签函数声明

    // 抽签void drawLots();
  • speechManager.cpp中实现抽签函数,并在开始比赛的相应抽签流程位置调用
// 抽签
void SpeechManager::drawLots() {cout << "第" << this->mIndex << "轮比赛选手正在抽签" << endl;cout << "抽签后演讲顺序如下:" << endl;if (this->mIndex == 1) {// 第一轮抽签random_shuffle(this->v1.begin(), this->v1.end());printVector(this->v1);} else {// 第二轮抽签random_shuffle(this->v2.begin(), this->v2.end());printVector(this->v2);}cout << "------------------" << endl;
}
  • 运行结果

在这里插入图片描述

比赛过程
  • 比赛过程为最重要部分,需要好好理解消化

  • 比赛流程梳理

    • 准备临时容器存放小组成绩,每处理完一组

    • 判断是第几轮比赛,选择对应的比赛选手

    • 遍历当前比赛选手,让10个评委调用随机函数去给每个选手打分

    • 得到分数后放到双端队列deque中进行降序排列,然后弹出头尾实现,去掉最高分和去掉最低分操作

    • 计算每个比赛者的总分和平均分,将打分数据放在降序排列的临时map容器中,每6个人为一组取前3名

    • 将取得的前3名放到下一轮要比赛的选手容器中,清空临时存放成绩的容器s

  • speechManager.hpp中添加比赛函数声明

    // 比赛void game();
  • speechManager.cpp中实现比赛函数,并在开始比赛的相应比赛流程位置调用
// 比赛
void SpeechManager::game() {cout << "------------第" << this->mIndex << "轮比赛开始了------------" << endl;// 准备临时容器存放小组成绩multimap<double, int, greater<double> > groupScore;// 记录人员个数,6人一组int num = 0;// vSrc 当前比赛选手容器vector<int> vSrc;if (this->mIndex == 1) {// 给v1容器的人打分vSrc = v1;} else {// 给v2容器的人打分vSrc = v2;}// 遍历所有选手进行比赛for (vector<int>::const_iterator it = vSrc.begin(); it != vSrc.end(); it++) {num++;// 10个评委打分deque<double> d;for (int i = 0; i < 10; i++) {// 随机一个600~1000的数,然后在除10// .f表示是一个小数double score = (rand() % 401 + 600) / 10.f;// cout << score << " ";d.push_back(score);}// 对分数进行降序排列sort(d.begin(), d.end(), greater<double>());// 去掉一个最高分d.pop_front();// 去掉一个最低分d.pop_back();// 累加总分double sum = accumulate(d.begin(), d.end(), 0.0f);// 计算平均分double avg = sum / (double) d.size();// 打印平均分// cout << "编号:" << *it << " 姓名:" << this->mSpeaker[*it].name << " 平均分:" << avg << endl;// 将平均分放到map容器中this->mSpeaker[*it].score[this->mIndex - 1] = avg;// 将打分数据放入到临时小组容器中groupScore.insert(make_pair(avg, *it));// 每6人取前三名if (num % 6 == 0) {cout << "第" << num / 6 << "小组比赛名次:" << endl;for (multimap < double, int, greater < double > > ::iterator it = groupScore.begin();it != groupScore.end();it++) {cout << "编号:" << it->second << " 姓名:" << this->mSpeaker[it->second].name << " 分数:" << it->first<< endl;}// 获取前三名,放入下一轮容器中int count = 0;for (multimap < double, int, greater < double > > ::iterator it = groupScore.begin();it != groupScore.end() && count < 3;it++, count++) {if (this->mIndex == 1) {v2.push_back(it->second);} else {v3.push_back(it->second);}}// 取完一次需要清空一次小组容器groupScore.clear();}}cout << "----------第" << this->mIndex << "轮比赛完毕------------" << endl;
}
显示晋级选手信息
  • speechManager.hpp中添加显示晋级选手函数声明
    // 显示晋级结果void showScore();
  • speechManager.cpp中实现显示晋级选手函数,并在开始比赛的相应比赛流程位置调用
// 显示晋级结果
void SpeechManager::showScore() {cout << "第" << this->mIndex << "轮晋级选手信息如下: " << endl;vector<int> v;if (this->mIndex == 1) {v = v2;} else {v = v3;}for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {cout << "编号:" << *it << " 姓名:" << this->mSpeaker[*it].name << " 分数:"<< this->mSpeaker[*it].score[this->mIndex - 1] << endl;}
}
第二轮比赛
  • 第二轮比赛只需要将index++,然后在开始比赛函数的第二轮调用对应的封装好的函数即可

  • 开始比赛整体调用代码如下

// 开始比赛
void SpeechManager::startSpeech() {// 第一轮比赛// 1.抽签this->drawLots();// 2.比赛this->game();// 3.显示晋级结果this->showScore();this->mIndex++;// 第二轮比赛// 1.抽签this->drawLots();// 2.比赛this->game();// 3.显示最终结果this->showScore();// 4.保存分数
}
  • 运行结果

在这里插入图片描述
在这里插入图片描述

保存分数
  • speechManager.hpp中添加保存分数函数声明
    // 保存分数void saveScore();
  • speechManager.cpp中实现保存分数函数,并在开始比赛流程最后位置调用
void SpeechManager::saveScore() {ofstream ofs;// 以追加输出的方式打开文件, csv中内容需要以,号分割ofs.open("speech.csv", ios::out | ios::app);// 将每个人的数据保存到文件for (vector<int>::iterator it = v3.begin(); it != v3.end(); it++) {ofs << *it << ","<< mSpeaker[*it].score[1] << ",";}ofs << endl;// 关闭文件ofs.close();cout << "记录已保存" << endl;
}

查看记录

从文件中加载记录
  • 文件不存在:提示直接返回

  • 文件存在但为空:先读一个字符看看是否读到了EOF

  • 文件存在不为空:

    • 先将读出的一个字符回写到文件中

    • 按行读取

    • 每读完一行按照逗号分割的方式将每一个编号和成绩的子字符串拿出来放入到临时vector中

    • 将一行vector中的内容放入往届成绩记录record容器中

将加载的记录进行展示
  • 遍历记录容器,将加载的内容一行一行的进行展示
功能实现
  • speechManager.hpp中添加对应的成员声明
    // 加载往届记录void loadRecord();// 查看往届记录void showRecord();// 记录比赛轮数int mIndex;// 文件是否为空标志bool fileIsEmpty;// 往届记录map<int, vector<string> > mRecord;
  • speechManager.cpp中实现相应的功能,在构造函数部分调用加载历史记录,在用户交互位置提供查看历史记录功能
// 查看分数
void SpeechManager::loadRecord() {ifstream ifs;ifs.open("speech.csv", ios::in);if (!ifs.is_open()) {// cout << "文件不存在" << endl;ifs.close();return;}// 文件存在// 文件被清空过的情况先读一个字符判断文件是否为空char ch;ifs >> ch;if (ifs.eof()) {cout << "文件为空" << endl;this->fileIsEmpty = true;ifs.close();return;}// 文件存在且不为空this->fileIsEmpty = false;// 将读取的字符放回ifs.putback(ch);string data;// index用来记录是第几届的数据,默认是第0届int index = 0;// 一行一行读while (ifs >> data) {// cout << data << endl;// 10005,83.6125,10007,82.7375,10008,80.725,// 存放每一届记录的前三编号和分数值vector <string> v;// pos查找逗号位置,默认为没有查到int pos = -1;// 从哪开始查找int start = 0;while (true) {// 从头开始查,pos = data.find(",", start);if (pos == -1) {break;}string tmp = data.substr(start, pos - start);v.push_back(tmp);// 下一次开始位置从上一个找到的逗号的下一个位置开始start = pos + 1;}// 将数据塞入往届成绩记录容器中this->mRecord.insert(make_pair(index, v));index++;}ifs.close();
}// 查看往届记录
void SpeechManager::showRecord() {cout << " this->fileIsEmpty" << this->fileIsEmpty << endl;if (this->fileIsEmpty) {cout << "文件不存在或记录为空" << endl;return;}this->loadRecord();for (map < int, vector < string > > ::iterator it = this->mRecord.begin(); it != this->mRecord.end();it++) {cout << "第" << it->first + 1 << "届:" << endl;cout << "冠军编号:" << it->second[0] << " 分数:" << it->second[1] << endl;cout << "亚军编号:" << it->second[2] << " 分数:" << it->second[3] << endl;cout << "季军编号:" << it->second[4] << " 分数:" << it->second[5] << endl;}
}

清空记录

  • speechManager.hpp中添加清空记录函数成员声明
    // 清空记录void clearRecord();
  • speechManager.hpp中实现清空记录的功能,并在用户交互界面提供清空记录的功能调用
// 清空记录
void SpeechManager::clearRecord() {cout << "确认清空?" << endl;cout << "1.确认" << endl;cout << "2.返回" << endl;int select;cin >> select;if (select == 1) {// 清空文件:trunc模式,如果文件存在,则删除文件并重新创建ofstream ofs("speech.csv", ios::trunc);ofs.close();// 初始化属性this->initSpeech();// 创建选手this->createSpeaker();// 加载往届成绩this->loadRecord();cout << "清空成功" << endl;}
}

完整项目位置

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/273010.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring boot 2.4.x 之前版本(对应spring-cloud-openfeign 3.0.0之前版本)feign请求异常逻辑

目录 feign SynchronousMethodHandler 第一部分 第二部分 第三部分 spring-cloud-openfeign LoadBalancerFeignClient ribbon AbstractLoadBalancerAwareClient 在之前写的文章配置基础上 https://blog.csdn.net/zlpzlpzyd/article/details/136060312 因为从 spring …

基于docker部署的Selenium Grid分布式自动化测试

01、什么是Selenium Grid Selenium Grid是Selenium套件的一部分&#xff0c;它专门用于并行运行多个测试用例在不同的浏览器、操作系统和机器上。 Selenium Grid有两个版本——老版本Grid 1和新版本Grid 2。我们只对新版本做介绍&#xff0c;因为Selenium团队已经逐渐遗弃老版…

【电路笔记】-PNP晶体管

PNP晶体管 文章目录 PNP晶体管1、概述2、PNP晶体管电路示例3、PNP晶体管识别1、概述 PNP 晶体管与我们在上一篇教程中看到的 NPN 晶体管器件完全相反。 在这种类型的 PNP 晶体管结构中,两个互连的二极管相对于之前的 NPN 晶体管是相反的。 这会产生正-负-正类型的配置,箭头…

Echarts 配置项 series 中的 data 是多维度

文章目录 需求分析 需求 如下图数据格式所示&#xff0c;现要求按照该格式进行绘制折线图 分析 在绘制折线图时&#xff0c;通常我们的 series 中的 data 数据是这样的格式 option {title: {text: Stacked Area Chart},tooltip: {trigger: axis,axisPointer: {type: cross…

车辆伤害VR安全教育培训复用性强

VR工地伤害虚拟体验是一种新兴的培训方式&#xff0c;它利用虚拟现实技术为参与者提供身临其境的体验。与传统的培训方式相比&#xff0c;VR工地伤害虚拟体验具有许多优势。 首先&#xff0c;VR工地伤害虚拟体验能够模拟真实的工作环境和事故场景&#xff0c;让参与者在安全的环…

论文阅读:Diffusion Model-Based Image Editing: A Survey

Diffusion Model-Based Image Editing: A Survey 论文链接 GitHub仓库 摘要 这篇文章是一篇基于扩散模型&#xff08;Diffusion Model&#xff09;的图片编辑&#xff08;image editing&#xff09;方法综述。作者从多个方面对当前的方法进行分类和分析&#xff0c;包括学习…

Python(38):Request的data需入参是json,用转换json.dumps(data)

Python接口自动化测试遇到问题:误传str类型给request 一&#xff1a;request接口请求数据用str传参报错&#xff0c;请求响应报错 排查原因&#xff1a;查看服务器报错是Json解析报错。 1.1、如果直接入参&#xff0c;进行request请求的数据&#xff1a; data请求值为&…

ElevenLabs用AI为Sora文生视频模型配音 ,景联文科技提供高质量真人音频数据集助力生成逼真音效

随着Open AI公司推出的Sora文生视频模型惊艳亮相互联网&#xff0c;AI语音克隆创企ElevenLabs又为Sora的演示视频生成了配音&#xff0c;所有的音效均由AI创造&#xff0c;与视频内容完美融合。 ElevenLabs的语音克隆技术能够从一分钟的音频样本中创建逼真的声音。为了实现这一…

2024蓝桥杯每日一题(双指针)

一、第一题&#xff1a;牛的学术圈 解题思路&#xff1a;双指针贪心 仔细思考可以知道&#xff0c;写一篇综述最多在原来的H指数的基础上1&#xff0c;所以基本方法可以是先求出原始的H指数&#xff0c;然后分类讨论怎么样提升H指数。 【Python程序代码】 n,l map(int,…

在win10中下载桌面版的docker并在docker中搭建运行基于linux的容器

在win10中下载桌面版的docker 1.背景 在很多时候需要linux系统部署项目&#xff0c;在win10中安装虚拟机并在虚拟机中安装linux系统比较繁琐&#xff0c;可以利用win10自带的hyper-v的虚拟机管理工具&#xff0c;打开该虚拟机管理工具&#xff0c;安装docker&#xff0c;并在…

[杂谈]QtCreator调试输出窗与chromium的调试输出窗

前言 在我接触最多的调试输出窗中&#xff0c;用得最多的就是QtCreator和chromium。发现一个有趣的现象记录一下。QtCreator在处理大量重复的输出的情况下&#xff0c;采用方式如下 QtCreator采用直接输出的方式&#xff0c;这样逻辑上很直观&#xff0c;但是当有大量的输出时…

<Linux> 初识线程

目录 前言&#xff1a; 一、什么是线程 &#xff08;一&#xff09;基本概念 &#xff08;二&#xff09;线程理解 &#xff08;三&#xff09;线程与进程的关系 &#xff08;四&#xff09;简单实用线程 &#xff08;五&#xff09;重谈虚拟地址空间 1. 页表的大小 2…

【UE5】游戏框架GamePlay

项目资源文末百度网盘自取 游戏框架 游戏 由 游戏模式(GameMode) 和 游戏状态(GameState) 所组成 加入游戏的 人类玩家 与 玩家控制器(PlayerController) 相关联 玩家控制器允许玩家在游戏中拥有 HUD&#xff0c;这样他们就能在关卡中拥有物理代表 玩家控制器还向玩家提供 …

深度学习-Softmax 回归 + 损失函数 + 图片分类数据集

Softmax 回归 损失函数 图片分类数据集 1 softmax2 损失函数1均方L1LossHuber Loss 3 图像分类数据集4 softmax回归的从零开始实现 1 softmax Softmax是一个常用于机器学习和深度学习中的激活函数。它通常用于多分类问题&#xff0c;将一个实数向量转换为概率分布。Softmax函…

docker安装和使用kafka

1. 启动zookeeper Kafka依赖zookeeper, 首先安装zookeeper -p&#xff1a;设置映射端口&#xff08;默认2181&#xff09; docker run --name zookeeper \--network app-tier \-e ALLOW_ANONYMOUS_LOGINyes \--restartalways \-d bitnami/zookeeper:latest2. 启动kafka docker…

LVS集群(Linux Virtual server)

集群概念lvs模型lvs调度算法lvs实现lvs高可用性&#xff0c;负载均衡 1 集群和分布式 系统性能扩展方式&#xff1a; Scale UP&#xff1a;垂直扩展&#xff0c;向上扩展,增强&#xff0c;性能更强的计算机运行同样的服务 升级单机的硬件设备Scale Out&#xff1a;水平扩展…

MySQL通过SQL语句进行递归查询

这里主要是针对于MySQL8.0以下版本&#xff0c;因为MySQL8.0版本出来了一个WITH RECURSIVE函数专门用来进行递归查询的 先看下表格数据&#xff0c;就是很普通的树结构数据&#xff0c;通过parentId关联上下级关系 下面我们先根据上级节点id递归获取所有的下级节点数据&#x…

回归测试重复测试

重复测试和回归测试在测试的过程中都会遇到过&#xff0c;出现的概率都是高频的&#xff0c;两者如何区分如下图&#xff1a; 回归测试 回归测试是什么&#xff1f; 回归测试&#xff08;Regression Testing&#xff09;是指在软件修改之后&#xff0c;对已有功能点重新执行测…

C/C++编程-理论学习-通信协议理论

通信协议理论 protobuf简述使用简介proto 文件为了nanopb 编译.proto文件修改生成器行为 streamsoutput streamsinput streams Data types(数据类型)Field callbacks(字段回调)Encoding callbacks(编码回调)Message descriptor(信息描述)三个关键字required、optional、repeate…

【C++】函数模板和类模板

目录 1.泛型编程 2.函数模板 2.1函数模板的定义格式 2.2函数模板的实例化 2.3函数模板参数的匹配原则 3.类模板 3.1类模板的定义格式 3.2类模板的实例化 3.3模板的分离编译 1.泛型编程 泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段…