基于STL的演讲比赛流程管理系统

  • 演讲比赛程序需求
    • 比赛规则
    • 程序功能
    • 成品展示
  • 实现过程
    • 创建主函数
    • 创建选手类
    • 创建管理类
  • 个人总结
    • 1.随机数的创建
    • 2.初始化容器和属性
    • 3.各容器和算法的操作
    • 4.文件操作

演讲比赛程序需求

比赛规则

  • 学校举行一场演讲比赛,共有12个人参加。比赛共两轮,第一轮为淘汰赛,第二轮为决赛。
  • 比赛方式:分组比赛,每组6个人;选手每次要随机分组,进行比赛
  • 第一轮分为两个小组,每组6个人。 整体按照选手编号进行抽签后顺序演讲。
  • 当小组演讲完后,淘汰组内排名最后的三个选手,前三名晋级,进入下一轮的比赛。
  • 第二轮为决赛,前三名胜出
  • 每轮比赛过后需要显示晋级选手的信息

程序功能

  • 开始演讲比赛:完成整届比赛的流程,每个比赛阶段需要给用户一个提示,用户按任意键后继续下一个阶段
  • 查看往届记录:查看之前比赛前三名结果,每次比赛都会记录到文件中,文件用.csv后缀名保存
  • 清空比赛记录:将文件中数据清空
  • 退出比赛程序:可以退出当前程序

成品展示








实现过程

创建主函数

在演讲比赛流程管理系统.cpp中实现

#include <iostream>
#include "speechManager.h"
#include <ctime>using namespace std;int main()
{//随机数种子 包含头文件ctimesrand((unsigned int)time(NULL));//实例化对象SpeechManager sm;/*出现的问题 此循环使用迭代器 迭代器是沟通算法和容器的桥梁 该系统主要用map容器存储数据 所以应用map的迭代器迭代器本质可以当作指针使用 for循环需要首尾边界 这里应当使用map容器定义出的对象m_Speaker 再调用出其begin和end区别与指针的是 这里可以用it++表示迭代器的后移 而指针不能这样操作*/测试案例//for (map<int, Speaker>::iterator it = sm.m_Speaker.begin(); it != sm.m_Speaker.end(); it++)//{//    cout << "选手编号:" << it->first << " 姓名:" << it->second.m_Name//       << " 分数:" << it->second.m_Score[0] << endl;//}int choice;while (true){sm.show_Menu();cout << "请输入您的选择:";cin >> choice;switch (choice){case 1://1.开始演讲比赛sm.startSpeech();break;case 2://2.查看往届记录sm.showRecord();break;case 3://3.清空比赛记录sm.clearRecord();break;case 0://0.退出比赛程序sm.exitSystem();break;default:cout << "输入有误" << endl;system("pause");system("cls");break;}}system("pause");return 0;
}

创建选手类

在speak.h头文件中实现

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

创建管理类

为什么要有管理类?—>管理类主要实现主函数的功能,分为.cpp和.h两个文件。 .h文件中主要写类的声明和成员函数及其属性, cpp文件中主要写各成员函数的实现

在speechManager.cpp中实现

#include "speechManager.h"
#include "speaker.h"
#include <algorithm>//管理类cpp文件主要是函数的实现 管理类.h头文件主要是函数的声明//构造函数
SpeechManager::SpeechManager()
{//初始化容器和属性this->initSpeech();//创建12名学生this->creatSpeaker();//加载往届记录this->loadRecord();
}//菜单功能
void SpeechManager::show_Menu()
{cout << "***************************************" << endl;cout << "************欢迎参加演讲比赛***********" << endl;cout << "*************1.开始演讲比赛************" << endl;cout << "*************2.查看往届记录************" << endl;cout << "*************3.清空比赛记录************" << endl;cout << "*************0.退出比赛程序************" << endl;cout << "***************************************" << endl;cout << endl;
}//退出功能
void SpeechManager::exitSystem()
{cout << "欢迎下次使用" << endl;system("pause");exit(0);
}//初始化容器和属性 记住:凡是在类里面定义的变量 在init函数中都要有初始化操作
void SpeechManager::initSpeech()
{//容器都置空this->v1.clear();this->v2.clear();this->vVictory.clear();this->m_Speaker.clear();//初始化比赛轮数this->m_Index = 1;//解决bug 将记录的容器也清空this->m_Record.clear();
}//初始化12个选手
void SpeechManager::creatSpeaker()
{string nameSeed = "ABCDEFGHIJKL";for (int i = 0; i < nameSeed.size(); i++){string name = "选手";name += nameSeed[i];//选手A,选手B 所以用数组nameSeed[i]//初始化选手类Speaker sp;sp.m_Name = name;//将每个选手复制到speaker类中成员函数for (int j = 0; j < 2; j++){sp.m_Score[j] = 0.0;}//编号this->v1.push_back(i + 10001);//vector容器尾插法用pushbackthis->m_Speaker.insert(pair<int, Speaker>(i + 10001, sp));//map容器插入用insert//错误原因 写成insert(make_pair(i + 10001), sp) //insert函数中需要创建对组分别为key和value key代表这里的编号i+10001 sp是Speaker数据结构中的变量 里面包含name和score//还可写成this->m_Speaker.insert(make_pair(i+1001, sp));}
}//开始比赛
void SpeechManager::startSpeech()
{//第一轮比赛//1、抽签this->speechDraw();//2、比赛this->speechContest();//3、显示晋级结果this->showScore();//第二轮比赛this->m_Index++;//1、抽签this->speechDraw();//2、比赛this->speechContest();//3、显示最终结果this->showScore();//4、保存分数到文件中this->saveRecord();//解决bug:重置比赛获取新记录 //初始化容器和属性this->initSpeech();//创建12名学生this->creatSpeaker();//加载往届记录this->loadRecord();cout << "本届比赛完毕!" << endl;system("pause");system("cls");
}//抽签
void SpeechManager::speechDraw()
{//第多少轮cout << "第<< " << this->m_Index << " >>轮比赛选手正在抽签" << endl;cout << "------------------------" << endl;cout << "抽签后演讲顺序如下" << endl;if (this->m_Index == 1){//第一轮random_shuffle(v1.begin(), v1.end());//打乱v1容器的顺序 洗牌算法需要包括头文件algorithm//遍历输出打乱后选手编号for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++){cout << *it << " ";}cout << endl;}else{//第二轮random_shuffle(v2.begin(), v2.end());for (vector<int>::iterator it = v2.begin(); it != v2.end(); it++){cout << *it << " ";}cout << endl;}cout << "------------------------" << endl;system("pause");
}//比赛
void SpeechManager::speechContest()
{cout << "-----------第" << this->m_Index << "轮比赛正式开始--------------" << endl;//准备临时的容器 存放小组成绩 存放的是前三名的平均分和编号 所以用降序//set和map默认都是升序less<T>multimap<double, int, greater<double>> groupScore;int num = 0;//记录人员个数6人一组vector<int> v_Src;//比赛选手容器 如果是第一轮则赋值为v1 反之则为v2if (this->m_Index == 1){v_Src = v1;}else{v_Src = v2;}//遍历所有选手进行比赛for (vector<int>::iterator it = v_Src.begin(); it != v_Src.end(); it++){num++;//评委打分 为什么要用quequ容器?--->目的在去除最高和最低分deque容器有pop_front和pop_backdeque<double> d;for (int i = 0; i < 10; i++){//对rand随机数的理解 rand()%401表示0至400的随机数 因为整数对401取余的值是0至400 然后加上600即400至600double score = (rand() % 401 + 600) / 10.f;    //600-1000的随机数 rand()%随机数//cout << score << " ";//测试d.push_back(score);}//cout << endl;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->m_Speaker[*it].m_Name//    << "获取的平均分为:" << avg << endl;//将平均分放入到map容器里 map容器重载了[]运算符*it即m_Speaker的索引this->m_Speaker[*it].m_Score[this->m_Index - 1] = avg;//将打分数据分数和编号 放入到临时小组容器中groupScore.insert(make_pair(avg, *it));//key是得分 value是具体选手编号 *it即m_Speaker的索引//每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->m_Speaker[it->second].m_Name << " 成绩:"<< this->m_Speaker[it->second].m_Score[this->m_Index - 1] << endl; }//取走 前三名int count = 0;for (multimap<double, int, greater<double>>::iterator it = groupScore.begin(); it != groupScore.end() && count < 3; it++, count++){if (this->m_Index == 1){v2.push_back((*it).second);}else{vVictory.push_back((*it).second);}}cout << endl;groupScore.clear();//小组容器清空 确保6个数据一存}}cout << " -------------第" << this->m_Index << "轮比赛完毕------------" << endl;system("pause");
}//显示比赛结果
void SpeechManager::showScore()
{cout << "-----------第" << this->m_Index << "轮晋级选手信息如下:------------" << endl;vector<int> v;if (this->m_Index == 1){v = v2;}else{v = vVictory;}//遍历输出 注意score也是个数组 需要有索引 this->m_Index-1//map容器重载了[] 所以可以用[]来找到key值对应的valuefor (vector<int>::iterator it = v.begin(); it != v.end(); it++){cout << "编号:" << *it << " 姓名:" << this->m_Speaker[*it].m_Name<< " 分数:" << this->m_Speaker[*it].m_Score[this->m_Index-1] << endl;}cout << endl;system("pause");system("cls");this->show_Menu();
}
//保存记录
void SpeechManager::saveRecord()
{//回顾文件操作 ofstream写数据 ifstream读数据 ios::out为写 ios::app表示往后追加数据ofstream ofs;//包括头文件fstreamofs.open("speech.csv", ios::out | ios::app);//将每个选手数据 逗号分割写入到csv文件中for (vector<int>::iterator it = vVictory.begin(); it != vVictory.end(); it++){ofs << *it << "," <<  this->m_Speaker[*it].m_Score[1] << ",";}ofs << endl;//关闭ofs.close();cout << "记录已经保存" << endl;//更改文件不为空状态 解决bug:当最开始文件没有数据的时候 进行第一届比赛后输入2显示文件为空或不存在this->fileIsEmpty = false;
}//读取记录
void SpeechManager::loadRecord()
{ifstream ifs("speech.csv", ios::in);//如果文件不存在则返回null 再对其求非则为真if (!ifs.is_open()){this->fileIsEmpty = true;//cout << "文件不存在" << endl;//关闭文件ifs.close();return;}//第二种情况 文件已经清空char ch;ifs >> ch;//如果ifs.eof()为真说明读到文件尾了if (ifs.eof()){//cout << "文件为空" << endl;this->fileIsEmpty = true;ifs.close();return;}//没有上述两种情况 说明文件存在this->fileIsEmpty = false;ifs.putback(ch);//将上面ifs>>ch读取的单个字符放回来 否则会少个字符string data;int index = 0;//默认第0届//ifs一直读data 直到读到末尾 在此过程中一直输出datawhile (ifs >> data){//cout << data << endl;//10002,86.675,10009,81.3,10007,78.55,//zhangsan@1qq.comvector<string> v;//存放6个string的字符串int pos = -1;//查到","位置的变量int start = 0;//起始位置while (true){pos = data.find(",", start);//find第二个参数默认起始位置为0 若未找到返回-1if (pos == -1){//没有找到break;}//第一个参数是开始截取的位置 第二个参数是截取的长度string temp = data.substr(start, pos - start);//cout << temp << endl;v.push_back(temp);start = pos + 1;//下一次进入循环是从逗号下一个字符开始判断}this->m_Record.insert(make_pair(index, v));index++;}ifs.close();测试 需要理解//for (map<int, vector<string>>::iterator it = m_Record.begin(); it != m_Record.end(); it++)//{//   cout << it->first << "冠军编号:" << it->second[0]//        << " 分数:" << it->second[1] << endl;//}
}//显示往届记录
void SpeechManager::showRecord()
{if (this->fileIsEmpty){cout << "文件为空或不存在!" << endl;}else{//需要理解for (int i = 0; i < this->m_Record.size(); i++){cout << "第" << i + 1 << "届"<< "冠军编号: " << this->m_Record[i][0] << " 得分: " << this->m_Record[i][1] << " "<< "亚军编号: " << this->m_Record[i][2] << " 得分: " << this->m_Record[i][3] << " "<< "季军编号: " << this->m_Record[i][4] << " 得分: " << this->m_Record[i][5] << endl;}}system("pause");system("cls");
}//清空文件
void SpeechManager::clearRecord()
{cout << "是否确定清空文件?" << endl;cout << "1、是" << endl;cout << "2、否" << endl;int select = 0;cin >> select;if (select == 1){//确认清空 ios::trunc方式 覆盖(删除)原文件所有内容ofstream ofs("speech.csv", ios::trunc);ofs.close();//初始化容器和属性this->initSpeech();//创建12名学生this->creatSpeaker();//加载往届记录this->loadRecord();cout << "清空成功!" << endl;}system("pause");system("cls");
}//析构函数
SpeechManager::~SpeechManager()
{}

在speechManager.h中实现

#pragma once
#include <iostream>
#include <vector>
#include <map>
#include "speaker.h"
#include <deque>
#include <functional>
#include <numeric>
#include <fstream>using namespace std;//管理类的理解  主要包含主函数运行时需要用到的函数,将其用管理类封装起来
//设计管理类
class SpeechManager
{public://构造函数SpeechManager();//菜单功能void show_Menu();//退出功能void exitSystem();//析构函数~SpeechManager();//初始化容器和属性void initSpeech();//初始化12个选手void creatSpeaker();//开始比赛void startSpeech();//抽签void speechDraw();//比赛void speechContest();//显示比赛结果void showScore();//保存记录void saveRecord();//读取记录void loadRecord();//显示往届记录void showRecord();//判断文件是否为空bool fileIsEmpty;//保存每届的数据map<int, vector<string>> m_Record;//清空文件void clearRecord();//成员属性//保存第一轮比赛选手编号容器 //<>内填int而非SpeechManager,注意编号是int类型 10001,10002...vector<int> v1;//第一轮晋级选手编号容器vector<int> v2;//胜出前三名选手编号容器vector<int> vVictory;//存放编号以及对应具体选手容器 //注意包含头文件"speaker" map容器<>中需要放两种数据类型map<int, Speaker> m_Speaker;//存放比赛轮数int m_Index;
};

个人总结

1.随机数的创建

//随机数 包含头文件#include<ctime>srand((unsigned int)time(NULL));double score = (rand() % 401 + 600) / 10.f;    rand()%

srand((unsigned int)time(NULL));是以时间创建一个随机数种子
double score = (rand() % 401 + 600) / 10.f; rand()%代表创建了一个大小从60到100的一个随机的双精度score

对rand() % 401 + 600的理解不要死记。rand() % 401表示正数对401取余 那么它的值为0-400,加上600则整体的范围是600-1000

2.初始化容器和属性

凡是在类里面定义的变量 在init函数中一定要有初始化的操作

3.各容器和算法的操作

1、this->v1.push_back(i + 10001);//vector容器尾插法用pushback
2、this->m_Speaker.insert(pair<int, Speaker>(i + 10001, sp));//map容器插入用insert
3、sort(d.begin(), d.end(), greater<double>());//排序(从头到尾降序)
4、double sum = accumulate(d.begin(), d.end(), 0.0f);//总分 头文件#include <numeric>
5、d.push_back(score);
6、d.pop_front();    //去除最高分
7、d.pop_back(); //去除最低分
8、groupScore.clear();//小组容器清空 确保6个数据一存
9、random_shuffle(v1.begin(), v1.end())//打乱v1容器的顺序
10、pos = data.find(",", start);//find第二个参数默认起始位置为0 若未找到返回-1

1、this->m_Speaker.insert(pair<int, Speaker>(i + 10001, sp));
也能写成this->m_Speaker.insert(make_pair(i+1001, sp));
2、sort(d.begin(), d.end(), greater<double>());排序算法great<>表示降序排列,less<>表示升序排序
3、double sum = accumulate(d.begin(), d.end(), 0.0f);以0.0为起始值将队列d的首至尾的元素求和

4.文件操作

 ofstream ofs;//包括头文件fstreamofs.open("speech.csv", ios::out | ios::app);ifstream ifs("speech.csv", ios::in);

1、文件操作包括写文件和读文件。写文件:ofstream ,ios::out读文件:ifstream,ios::in
2、os::app追加写
3、if (!ifs.is_open())判断文件是否打开
4、关闭文件ifs.close();

  • 文件不存在
 if (!ifs.is_open()){this->fileIsEmpty = true;//cout << "文件不存在" << endl;//关闭文件ifs.close();return;}
  • 文件已经清空
 char ch;ifs >> ch;//如果ifs.eof()为真说明读到文件尾了if (ifs.eof()){//cout << "文件为空" << endl;this->fileIsEmpty = true;ifs.close();return;}

累的时候,说明在走上坡路

黑马C++项目实操演讲比赛流程管理系统相关推荐

  1. 【49C++项目案例:演讲比赛流程管理系统】

    文章目录 演讲比赛流程管理系统 1.演讲比赛程序需求 1.1 比赛规则 1.2 程序功能 1.3 程序效果图 2.项目创建 2.1 创建项目 2.2 添加文件 3.创建管理类 3.1 创建文件 3.2 ...

  2. C++项目实战 —— 演讲比赛流程管理系统

    演讲比赛流程管理系统 文章目录 演讲比赛流程管理系统 1.演讲比赛程序需求 1.1 比赛规则 1.2 程序功能 2.项目创建 3.创建管理类 3.1 创建文件 3.2 头文件实现 3.3 源文件实现 ...

  3. c++小项目:基于STL的演讲比赛流程管理系统

    一.项目目的 运用c++实现一个基于STL的演讲比赛流程管理系统. 比赛方式 共两轮,第一轮为分组淘汰赛,第二轮为决赛,共有十名评委,打分方式为去掉最高分和最低分的平均分为基准 第一轮共两组,每组六人 ...

  4. 演讲比赛流程管理系统C++

    参考B站黑马视频 演讲比赛流程管理系统 1.1.比赛规则 学校举行演讲比赛,共有12人参加.比赛共两轮,第一轮为淘汰赛,第二轮为决赛 每名选手都有对应的编号,如10001 ~ 10012 比赛方式:分 ...

  5. 【带你敲】演讲比赛流程管理系统

    CSDN话题挑战赛第2期 参赛话题:学习笔记 1. 演讲比赛程序需求 1.1 比赛规则 学校举行一场演讲比赛,共有12个人参加.比赛共两轮,第一轮为淘汰赛,第二轮为决赛. 比赛方式:分组比赛,每组6个 ...

  6. C++阶段06笔记01【基于STL的演讲比赛流程管理系统】

    C++匠心之作-从0到1入门学编程[视频+课件+笔记+源码] 目录 1.演讲比赛程序需求 1.1.比赛规则 1.2.程序功能 1.3.程序效果图 2.项目创建 2.1.创建项目 2.2.添加文件 3. ...

  7. 演讲比赛流程管理系统(C++)

    各位读者朋友,大家好!本篇文章主要内容是将黑马程序员(C++)的演讲比赛流程管理系统的源代码展现给大家.原码的大部分与黑马程序员老师写的代码一致,我只是对其中的一小部分做了优化,比如用户输入自己的选择 ...

  8. C++提高编程(六)—— 案例 :演讲比赛流程管理系统(上)

    C++系列内容的学习目录 → \rightarrow →C++学习系列内容汇总. 1. 演讲比赛程序需求 1.1 比赛规则 1.2 程序功能 1.3 程序效果图 2. 创建项目 3. 创建管理类 3. ...

  9. 演讲比赛流程管理系统

    演讲比赛流程管理系统 1. 演讲比赛程序需求 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QSVuxGip-1615387131493)(assets/1548154 ...

最新文章

  1. MDA模型定义及扩展
  2. [转]设计高效SQL: 一种视觉的方法
  3. Asia Yokohama Regional Contest 2018 G题 What Goes Up Must Come Down(树状数组求逆序对)
  4. centos rpm 安装 perl_Linux【常用软件安装篇】
  5. 两个重要而又容易被忽视的角色
  6. mapbox 加载json数据 和数据中颜色 和高度 并根据数值加载颜色
  7. 升级python到2.7版本pip不可用
  8. SVN下载、安装、配置及使用方法
  9. 可曾听闻【大话】二字
  10. 如何分析加上SE壳的.net程序
  11. FPGA丨图像二值化
  12. SLAM中的边缘化舒尔补
  13. 不错的javascript极品日历
  14. 牛客输入输出(依图科技)
  15. javaWeb之Response
  16. Android 通知栏图标
  17. http返回码301、302、307、305含义和区别
  18. 中职计算机技术教学计划,中职计算机应用基础教学计划.doc
  19. 全面解析马斯克的产业帝国
  20. 车牌识别一体机二次开发

热门文章

  1. CUMT 1031 Order
  2. 手机汉字输入法欲立国家标准
  3. 兔子繁衍问题(C语言)
  4. 大数据笔记10—java基础篇6(集合1-Collection)
  5. Github Page绑定至个人域名
  6. 2021交通银行面试问题总结
  7. php 无法加载activex,IE无法加载 Activex 控件的解决办法
  8. 说说谢霆锋的音乐创作[转]
  9. 腾讯Flink实践:实时计算平台Oceanus建设历程
  10. CSS实现个性化水球图