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

C++匠心之作-从0到1入门学编程【视频+课件+笔记+源码】

目录

1、演讲比赛程序需求

1.1、比赛规则

1.2、程序功能

1.3、程序效果图

2、项目创建

2.1、创建项目

2.2、添加文件

3、创建管理类

3.1、创建文件

3.2、头文件实现

3.3、源文件实现

4、菜单功能

4.1、添加成员函数

4.2、菜单功能实现

4.3、测试菜单功能

5、退出功能

5.1、提供功能接口

5.2、实现退出功能

5.3、测试功能

6、演讲比赛功能

6.1、功能分析

6.2、创建选手类

6.3、比赛

6.3.1、成员属性添加

6.3.2、初始化属性

6.3.3、创建选手

6.3.4、开始比赛成员函数添加

6.3.5、抽签

6.3.6、开始比赛

6.3.7、显示比赛分数

6.3.8、第二轮比赛

6.4、保存分数

7、查看记录

7.1、读取记录分数

7.2、查看记录功能

7.3、测试功能

7.4、bug解决

8、清空记录

8.1、清空记录功能实现

8.2、测试清空

9、案例代码

9.1、演讲比赛流程管理系统.cpp

9.2、speaker.h

9.3、speechManager.cpp

9.4、speechManager.h


1、演讲比赛程序需求

1.1、比赛规则

  1. 学校举行一场演讲比赛,共有12个人参加。比赛共两轮,第一轮为淘汰赛,第二轮为决赛。

  2. 比赛方式:分组比赛,每组6个人;选手每次要随机分组,进行比赛。

  3. 每名选手都有对应的编号,如:10001~10012。

  4. 第一轮分为两个小组,每组6个人。 整体按照选手编号进行抽签后顺序演讲。

  5. 当小组演讲完后,淘汰组内排名最后的三个选手,前三名晋级,进入下一轮的比赛。

  6. 第二轮为决赛,前三名胜出

  7. 每轮比赛过后需要显示晋级选手的信息

1.2、程序功能

  1. 开始演讲比赛:完成整届比赛的流程,每个比赛阶段需要给用户一个提示,用户按任意键后继续下一个阶段。

  2. 查看往届记录:查看之前比赛前三名结果,每次比赛都会记录到文件中,文件用.csv后缀名保存。

  3. 清空比赛记录:将文件中数据清空。

  4. 退出比赛程序:可以退出当前程序。

1.3、程序效果图

2、项目创建

创建项目步骤如下:1.创建新项目;2.添加文件。

2.1、创建项目

打开vs2017后,点击创建新项目,创建新的C++项目。如图:

填写项目名称以及选取项目路径,点击确定生成项目。

2.2、添加文件

右键源文件,进行添加文件操作。

填写文件名称,点击添加。

生成文件成功,效果如下图。

至此,项目已创建完毕。

3、创建管理类

功能描述:1.提供菜单界面与用户交互;2.对演讲比赛流程进行控制;3.与文件的读写交互。

3.1、创建文件

在头文件和源文件的文件夹下分别创建speechManager.h和speechManager.cpp文件。

3.2、头文件实现

在speechManager.h中设计管理类,代码如下:

#pragma once
#include<iostream>
using namespace std;

//演讲管理类
class SpeechManager {
    public:
	    //构造函数
	    SpeechManager();

	    //析构函数
	    ~SpeechManager();
};

3.3、源文件实现

在speechManager.cpp中将构造和析构函数空实现补全。

#include "speechManager.h"

SpeechManager::SpeechManager() {
}

SpeechManager::~SpeechManager() {
}

至此演讲管理类以创建完毕。

4、菜单功能

功能描述:与用户的沟通界面。

4.1、添加成员函数

在管理类speechManager.h中添加成员函数 void show_Menu();。

4.2、菜单功能实现

在管理类speechManager.cpp中实现show_Menu()函数。

void SpeechManager::show_Menu() {
	cout << "********************************************" << endl;
	cout << "************* 欢迎参加演讲比赛 ************" << endl;
	cout << "*************  1.开始演讲比赛  *************" << endl;
	cout << "*************  2.查看往届记录  *************" << endl;
	cout << "*************  3.清空比赛记录  *************" << endl;
	cout << "*************  0.退出比赛程序  *************" << endl;
	cout << "********************************************" << endl;
	cout << endl;
}

4.3、测试菜单功能

在演讲比赛流程管理系统.cpp中测试菜单功能,代码:

#include<iostream>
using namespace std;
#include "speechManager.h"

int main() {
	SpeechManager sm;
	sm.show_Menu();
	system("pause");
	return 0;
}

运行效果如图:

菜单界面搭建完毕。

5、退出功能

5.1、提供功能接口

在main函数中提供分支选择,提供每个功能接口,代码:

int main() {
	SpeechManager sm;
	int choice = 0;//用来存储用户的选项
	while (true) {
		sm.show_Menu();

		cout << "请输入您的选择: " << endl;
		cin >> choice; // 接受用户的选项

		switch (choice) {
		case 1:  //开始比赛
			break;
		case 2:  //查看记录
			break;
		case 3:  //清空记录
			break;
		case 0:  //退出系统
			break;
		default:
			system("cls"); //清屏
			break;
		}
	}

	system("pause");
	return 0;
}

5.2、实现退出功能

在speechManager.h中提供退出系统的成员函数 void exitSystem();

在speechManager.cpp中提供具体的功能实现。

void SpeechManager::exitSystem() {
	cout << "欢迎下次使用!" << endl;
	system("pause");
	exit(0);
}

5.3、测试功能

在main函数分支0选项中,调用退出程序的接口。

运行测试效果如图:

6、演讲比赛功能

6.1、功能分析

比赛流程分析:

抽签 → 开始演讲比赛 → 显示第一轮比赛结果 → 抽签 → 开始演讲比赛 → 显示前三名结果 → 保存分数。

6.2、创建选手类

  • 选手类中的属性包含:选手姓名、分数。

  • 头文件中创建speaker.h文件,并添加代码:

#pragma once
#include<iostream>
using namespace std;

class Speaker {
public:
	string m_Name;//姓名
	double m_Score[2];//分数,最多有两轮得分
};

6.3、比赛

6.3.1、成员属性添加

在speechManager.h中添加属性:

	//比赛选手容器 12人
	vector<int>v1;

	//第一轮晋级容器 6人
	vector<int>v2;

	//胜利前三名容器 3人
	vector<int>vVictory;

	//存放编号以及对应的具体选手容器
	map<int, Speaker> m_Speaker;

6.3.2、初始化属性

  • 在speechManager.h中提供开始比赛的的成员函数 void initSpeech();

	//初始化属性
	void initSpeech();
  • 在speechManager.cpp中实现 void initSpeech();

void SpeechManager::initSpeech() {
	//容器保证为空
	this->v1.clear();  
	this->v2.clear();
	this->vVictory.clear();
	this->m_Speaker.clear();
	//初始化比赛轮数
	this->m_Index = 1;
}
  • SpeechManager构造函数中调用 void initSpeech();

SpeechManager::SpeechManager() {
	//初始化属性
	this->initSpeech();
}

6.3.3、创建选手

  • 【1】在speechManager.h中提供开始比赛的的成员函数 void createSpeaker();

	//初始化创建12名选手
	void createSpeaker();
  • 【2】在speechManager.cpp中实现 void createSpeaker();

void SpeechManager::createSpeaker() {
	string nameSeed = "ABCDEFGHIJKL";
	for (int i = 0; i < nameSeed.size(); i++) {
		string name = "选手";
		name += nameSeed[i];

		Speaker sp;
		sp.m_Name = name;
		for (int i = 0; i < 2; i++) {
			sp.m_Score[i] = 0;
		}

		//12名选手编号
		this->v1.push_back(i + 10001);

		//选手编号以及对应的选手存放到map容器中
		this->m_Speaker.insert(make_pair(i + 10001, sp));
	}
}
  • 【3】SpeechManager类的构造函数中调用 void createSpeaker();

SpeechManager::SpeechManager() {
    //初始化属性
	this->initSpeech();
    
	//创建选手
	this->createSpeaker();
}
  • 【4】测试在main函数中,可以在创建完管理对象后,使用下列代码测试12名选手初始状态。

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;
}
  • 【5】测试效果如图:

  • 【6】测试完毕后,可以将测试代码删除或注释。

6.3.4、开始比赛成员函数添加

  • 在speechManager.h中提供开始比赛的的成员函数 void startSpeech();

  • 该函数功能是主要控制比赛的流程。

	//开始比赛 - 比赛流程控制
	void startSpeech();
  • 在speechManager.cpp中将startSpeech的空实现先写入。

  • 我们可以先将整个比赛的流程写到函数中。

//开始比赛
void SpeechManager::startSpeech() {
	//第一轮比赛
	//1、抽签
	//2、比赛
	//3、显示晋级结果

	//第二轮比赛
	//1、抽签
	//2、比赛
	//3、显示最终结果
	//4、保存分数
}

6.3.5、抽签

功能描述:正式比赛前,所有选手的比赛顺序需要打乱,我们只需要将存放选手编号的容器打乱次序即可。

  • 在speechManager.h中提供抽签的的成员函数 void speechDraw();

	//抽签
	void speechDraw();
  • 在speechManager.cpp中实现成员函数 void speechDraw();

void SpeechManager::speechDraw() {
	cout << "第 << " << this->m_Index << " >> 轮比赛选手正在抽签!"<<endl;
	cout << "---------------------" << endl;
	cout << "抽签后演讲顺序如下:" << endl;
	if (this->m_Index == 1) {
		random_shuffle(v1.begin(), v1.end());
		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");
	cout << endl;
}
  • 在startSpeech比赛流程控制的函数中,调用抽签函数:

  • 在main函数分支1选项中调用开始比赛的接口:

  • 测试:

6.3.6、开始比赛

  • 在speechManager.h中提供比赛的的成员函数 void speechContest();

	//比赛
	void speechContest();
  • 在speechManager.cpp中实现成员函数 void speechContest();

void SpeechManager::speechContest() {
	cout << "------------- 第"<< this->m_Index << "轮正式比赛开始:------------- " << endl;

	multimap<double, int, greater<int>> groupScore; //临时容器,保存key分数,value选手编号

	int num = 0; //记录人员数,6个为1组

	vector <int>v_Src;//比赛的人员容器
	if (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++;

		//评委打分
		deque<double>d;
		for (int i = 0; i < 10; i++) {
			double score = (rand() % 401 + 600) / 10.f;//600~1000
			//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->m_Speaker[*it].m_Name << " 获取平均分为: " << avg << endl;  //打印分数
		this->m_Speaker[*it].m_Score[this->m_Index - 1] = avg;

		//6个人一组,用临时容器保存
		groupScore.insert(make_pair(avg, *it));
		if (num % 6 == 0) {
			cout << "第" << num / 6 << "小组比赛名次:" << endl;
			for (multimap<double, int, greater<int>>::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<int>>::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);
				}
			}
			groupScore.clear();
			cout << endl;
		}
	}
	cout << "------------- 第" << this->m_Index << "轮比赛完毕!  ------------- " << endl;
	system("pause");
}
  • 在startSpeech比赛流程控制的函数中,调用比赛函数:

  • 再次运行代码,测试比赛:

6.3.7、显示比赛分数

  • 在speechManager.h中提供比赛的的成员函数 void showScore();

	//显示比赛结果
	void showScore();
  • 在speechManager.cpp中实现成员函数 void showScore();

void SpeechManager::showScore() {
	cout << "---------第" << this->m_Index << "轮晋级选手信息如下:-----------" << endl;
	vector<int>v;
	if (this->m_Index == 1) {
		v = v2;
	} else {
		v = vVictory;
	}

	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << "选手编号:" << *it << ",姓名:" << m_Speaker[*it].m_Name << ",得分:" << m_Speaker[*it].m_Score[this->m_Index - 1] << endl;
	}
	cout << endl;

	system("pause");
	system("cls");
	this->show_Menu(); 
}
  • 在startSpeech比赛流程控制的函数中,调用显示比赛分数函数:

  • 运行代码,测试效果:

6.3.8、第二轮比赛

第二轮比赛流程同第一轮,只是比赛的轮是+1,其余流程不变。

在startSpeech比赛流程控制的函数中,加入第二轮的流程。

测试,将整个比赛流程都跑通。

6.4、保存分数

功能描述:将每次演讲比赛的得分记录到文件中。

功能实现:

  • 在speechManager.h中添加保存记录的成员函数 void saveRecord();

	//保存记录
	void saveRecord();
  • 在speechManager.cpp中实现成员函数 void saveRecord();

void SpeechManager::saveRecord() {
	ofstream ofs;
	ofs.open("speech.csv", ios::out | ios::app);//用输出的方式打开文件--写文件

	//将每个人数据写入到文件中
	for (vector<int>::iterator it = vVictory.begin(); it != vVictory.end(); it++) {
		ofs << *it << "," << m_Speaker[*it].m_Score[1] << ",";
	}
	ofs << endl;

	ofs.close();//关闭文件

	cout << "记录已经保存!" << endl;
}
  • 在startSpeech比赛流程控制的函数中,最后调用保存记录分数函数。

  • 测试,整个比赛完毕后记录保存情况。

利用记事本打开文件 speech.csv,里面保存了前三名选手的编号以及得分。

至此,整个演讲比赛功能制作完毕!

7、查看记录

7.1、读取记录分数

  • 在speechManager.h中添加保存记录的成员函数 void loadRecord();

  • 添加判断文件是否为空的标志 bool fileIsEmpty;

  • 添加往届记录的容器 map<int, vector<string>> m_Record;

其中m_Record 中的key代表第几届,value记录具体的信息。

	//读取记录
	void loadRecord();

	//文件为空的标志
	bool fileIsEmpty;

	//往届记录
	map<int, vector<string>> m_Record;
  • 在speechManager.cpp中实现成员函数 void loadRecord();

void SpeechManager::loadRecord() {
	ifstream ifs("speech.csv", ios::in); //输入流对象读取文件

	if (!ifs.is_open()) {
		this->fileIsEmpty = true;
		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;
	int index = 0;
	while (ifs >> data) {
		//cout << data << endl;
		vector<string>v;

		int pos = -1;
		int start = 0;

		while (true) {
			pos = data.find(",", start); //从0开始查找 ','
			if (pos == -1) {
				break; //找不到break返回
			}
			string tmp = data.substr(start, pos - start); //找到了“,”进行分割。参数1起始位置,参数2截取长度
			v.push_back(tmp);
			start = pos + 1;
		}

		this->m_Record.insert(make_pair(index, v));
		index++;
	}

	ifs.close();
}
  • 在SpeechManager构造函数中调用获取往届记录函数。

7.2、查看记录功能

  • 在speechManager.h中添加保存记录的成员函数 void showRecord();

	//显示往届得分
	void showRecord();
  • 在speechManager.cpp中实现成员函数 void showRecord();

void SpeechManager::showRecord() {
	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");
}

7.3、测试功能

在main函数分支2选项中,调用查看记录的接口。

显示效果如图(本次测试添加了4条记录):

7.4、bug解决

目前程序中有几处bug未解决:

  • 【1】查看往届记录,若文件不存在或为空,并未提示。

  • 解决方式:在showRecord函数中,开始判断文件状态并加以判断。

  • 【2】若记录为空或不存在,比完赛后依然提示记录为空

  • 解决方式:saveRecord中更新文件为空的标志。

  • 【3】比完赛后查不到本届比赛的记录,没有实时更新。

  • 解决方式:比赛完毕后,所有数据重置。

  • 【4】在初始化时,没有初始化记录容器。

  • 解决方式:initSpeech中添加初始化记录容器。

  • 【5】每次记录都是一样的。

  • 解决方式:在main函数一开始添加随机数种子。
srand((unsigned int)time(NULL));

所有bug解决后测试:

8、清空记录

8.1、清空记录功能实现

  • 在speechManager.h中添加保存记录的成员函数 void clearRecord();

	//清空记录
	void clearRecord();
  • 在speechManager.cpp中实现成员函数 void clearRecord();

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();

		//创建选手
		this->createSpeaker();

		//获取往届记录
		this->loadRecord();		

		cout << "清空成功!" << endl;
	}
	system("pause");
	system("cls");
}

8.2、测试清空

在main函数分支3选项中,调用清空比赛记录的接口。

运行程序,测试清空记录:

speech.csv中记录也为空。

至此本案例结束! ^_^

9、案例代码

9.1、演讲比赛流程管理系统.cpp

#include "speechManager.h"
#include <iostream>
#include <string>
#include <ctime>
using namespace std;

int main() {
	srand((unsigned int)time(NULL));//随机数种子
	SpeechManager sm;//创建管理类对象
	//测试12名选手创建
	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 = 0;//用于存储用户输入
	while (true) {
		sm.show_Menu();
		cout << "请输入您的选择:" << endl;
		cin >> choice;
		switch (choice) {
			case 1: //开始比赛
				sm.startSpeech();
				break;
			case 2: //查看往届比赛记录
				sm.showRecord();
				break;
			case 3: //清空比赛记录
				sm.clearRecord();
				break;
			case 0: //退出系统
				sm.exitSystem();
				break;
			default:
				system("cls");//清屏
				break;
		}
	}
	system("pause");
	return 0;
}

9.2、speaker.h

#pragma once
#include <iostream>
using namespace std;

class Speaker {//选手类
	public:
		string m_Name;//姓名
		double m_Score[2];//分数,最多有两轮得分
};

9.3、speechManager.cpp

#include "speechManager.h"

//构造函数
SpeechManager::SpeechManager() {
	//初始化容器和属性
	this->initSpeech();

	//创建12名选手
	this->createSpeaker();

	//加载往届记录
	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);
}

void SpeechManager::initSpeech() {
	//容器都置空
	this->v1.clear();
	this->v2.clear();
	this->vVictory.clear();
	this->m_Speaker.clear();

	//初始化比赛轮数
	this->m_Index = 1;

	//将记录的容器 也清空
	this->m_Record.clear();
}

//创建12名选手
void SpeechManager::createSpeaker() {
	string nameSeed = "ABCDEFGHIJKL";
	for (int i = 0; i < nameSeed.size(); i++) {
		string name = "选手";
		name += nameSeed[i];

		//创建具体选手
		Speaker sp;
		sp.m_Name = name;

		for (int j = 0; j < 2; j++) {
			sp.m_Score[j] = 0;
		}

		//创建选手编号并且放入到v1容器中
		this->v1.push_back(i + 10001);

		//选手编号以及对应选手放入到map容器中
		this->m_Speaker.insert(make_pair(i + 10001, sp));
	}
}

//开始比赛 比赛整个流程控制函数
void SpeechManager::startSpeech() {
	//第一轮开始比赛
	//1、抽签
	this->speechDraw();
	//2、比赛
	this->speechContest();
	//3、显示晋级结果
	this->showScore();

	//第二轮开始比赛
	this->m_Index++;
	//1、抽签
	this->speechDraw();
	//2、比赛
	speechContest();
	//3、显示最终结果
	this->showScore();
	//4、保存分数到文件中
	this->saveRecord();

	//重置比赛,获取记录
	//初始化容器和属性
	this->initSpeech();

	//创建12名选手
	this->createSpeaker();

	//加载往届记录
	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());
		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");
	cout << endl;
}

//比赛
void SpeechManager::speechContest() {
	cout << "----------- 第" << this->m_Index << " 轮比赛正式开始! --------------" << endl;

	//准备临时容器存放小组成绩
	multimap<double, int, greater<double>> groupScore;

	int num = 0; //记录人员个数,6人一组

	vector<int> v_Src; //比赛选手容器
	if (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++;
		//评委打分
		deque<double> d;
		for (int i = 0; i < 10; i++) {
			double score = (rand() % 401 + 600) / 10.f;//600~1000
			//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容器里
		this->m_Speaker[*it].m_Score[this->m_Index - 1] = avg;

		//将打分数据 放入到临时小组容器中
		groupScore.insert(make_pair(avg, *it)); //key是得分,value是具体选手编号
		//每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);
				}
			}
			groupScore.clear(); //小组容器清空
			cout << endl;
		}
	}
	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;
	}
	for (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 ofs;
	ofs.open("speech.csv", ios::out | ios::app);//用追加的方式写文件

	//将每个选手数据写入到文件中
	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;

	//更改文件不为空状态
	this->fileIsEmpty = false;
}

//读取记录
void SpeechManager::loadRecord() {
	ifstream ifs("speech.csv", ios::in);//读文件

	if (!ifs.is_open()) {
		this->fileIsEmpty = true;
		// 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;
	int index = 0;

	while (ifs >> data) {
		//cout << data << endl;
		//10002,86.675,10009,81.3,10007,78.55,

		vector<string> v;//存放6个string字符串

		int pos = -1;//查到","位置的变量
		int start = 0;

		while (true) {
			pos = data.find(",", start);
			if (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) {
		//确认清空
		ofstream ofs("speech.csv", ios::trunc);
		ofs.close();

		//初始化容器和属性
		this->initSpeech();

		//创建12名选手
		this->createSpeaker();

		//加载往届记录
		this->loadRecord();

		cout << "清空成功!" << endl;
	}
	system("pause");
	system("cls");
}

//析构函数
SpeechManager::~SpeechManager() {
}

9.4、speechManager.h

#pragma once//防止头文件重复编译
#include "speaker.h"
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <deque>
#include <functional>
#include <numeric>
#include <string>
#include <fstream>
using namespace std;

class SpeechManager {//设计演讲管理类
	public:
		//构造函数
		SpeechManager();

		//菜单功能
		void show_Menu();

		//退出系统
		void exitSystem();

		//析构函数
		~SpeechManager();

		//初始化容器和属性
		void initSpeech();

		//创建12名选手
		void createSpeaker();

		//开始比赛,比赛整个流程控制函数
		void startSpeech();

		//抽签
		void speechDraw();

		//比赛
		void speechContest();

		//显示得分
		void showScore();

		//保存记录
		void saveRecord();

		//读取记录
		void loadRecord();

		//显示往届记录
		void showRecord();

		//清空文件
		void clearRecord();

		//判断文件是否为空
		bool fileIsEmpty;

		//存放往届记录的容器
		map<int, vector<string>> m_Record;

		//成员属性
		//保存第一轮比赛选手编号容器
		vector<int> v1;

		//第一轮晋级选手编号容器
		vector<int> v2;

		//胜出前三名选手编号容器
		vector<int> vVictory;

		//存放编号以及对应具体选手容器
		map<int, Speaker> m_Speaker;

		//存放比赛轮数
		int m_Index;
};

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340