#pragma once
#include
#include
#include
#include
#include
#include
#include //accumulate
#include
#include
#include //设置打印精度
#include //内建函数对象
#include"Speaker.h"
#define FILENAME "speech.csv"
using namespace std;
class SpeechContestManager
{
public:
vector<int>v1;
vector<int>v2;
vector<int>v_victory;
map<int, Speaker>m_speaker;
map<int, vector<string>>m_record;
int m_round;
bool emptyfile;
SpeechContestManager();
void Menu();//菜单
void Exit();//退出
void InitSpeech();//初始化演讲
void CreatSpeaker();//设置比赛人的信息
void StartSpeech();//开始演讲比赛
void SpeechLot();//比赛抽签
void SpeechConst();//进行比赛
void ShowScore();//展示分数
void SaveRecord();//保存记录
void LoadRecord();//载入记录
void ShowRecord();//展示记录
void ClearRecord();//清空记录
~SpeechContestManager();
};
为了便于理解,使用v1,v2分别存储两轮的选手,
v_victory存储赢得比赛的编号
这里还需创建一个演讲者类
#pragma once
#include
#include
using namespace std;
class Speaker
{
public:
string m_name;
double m_score[2];
};
存储姓名和两轮的比赛成绩
用map容器的对组存储编号和Speaker类的属性,用于存储选手信息
第二个map则是用于存储获奖者信息,读文件,展示文件的载体
m_round表示轮数
bool emptyfile表明文件状态
是调用展示记录函数时的判断依据
void SpeechContestManager::Menu()
{
cout << "********************************************" << endl;
cout << "********* 欢迎参加演讲比赛 *********" << endl;
cout << "********* 1.开始演讲比赛 *********" << endl;
cout << "********* 2.查看往期记录 *********" << endl;
cout << "********* 3.清空比赛记录 *********" << endl;
cout << "********* 0.退出比赛程序 *********" << endl;
cout << "********************************************" << endl;
cout << endl;
}
提示用户进行输入
#include"SpeechcontestManager.h"
int main()
{
srand((unsigned int)time(NULL));
SpeechContestManager scm;
scm.InitSpeech();
scm.CreatSpeaker();
scm.LoadRecord();
int choice;
do {
scm.Menu();
cout << "请选择:" << endl;
cin >> choice;
switch (choice)
{
case 1:
scm.StartSpeech();
break;
case 2:
scm.ShowRecord();
break;
case 3:
scm.ClearRecord();
break;
case 0:
scm.Exit();
default:
system("cls");
}
} while (choice);
return 0;
}
要设置时间戳,在抽签和生成成绩时需要用到
实例化管理对象,先进行初始化,选手设置,载入记录。
调用菜单,根据用户输入调用不同功能函数,选择错误进行清屏即可
SpeechContestManager::SpeechContestManager()
{
this->InitSpeech();
}
调用InitSpeech初始化,其实没必要,main函数里又手动调用了一遍
void SpeechContestManager::Exit()
{
cout << "欢迎下次使用!" << endl;
system("pause");
exit(0);
}
exit的功 能: 关闭所有文件,终止正在执行的进程。
exit(1)表示异常退出.这个1是返回给操作系统的。
exit(x)(x不为0)都表示异常退出
exit(0)表示正常退出
exit()的参数会被传递给一些操作系统,包括UNIX,Linux,和MS DOS,以供其他程序使用。
void SpeechContestManager::InitSpeech()
{
this->v1.clear();
this->v2.clear();
this->v_victory.clear();
this->m_speaker.clear();
this->m_record.clear();
this->m_round =1;
}
就是对类内成员变量进行初始化操作
轮数置为1
void SpeechContestManager::CreatSpeaker()
{
string nameSeed[12] = { { "白羊" },{"金牛"},{"双子"},{"巨蟹"},{"狮子"},{"处女"}
,{"天秤"},{"天蝎"},{"射手"},{"摩羯"},{"水瓶"},{"双鱼"} };
for (int i = 0; i < 12; i++)
{
Speaker sp;
sp.m_name = nameSeed[i];
for (int j = 0; j < 2; j++)
sp.m_score[j] = 0;
this->v1.push_back(i + 1001);
this->m_speaker.insert(make_pair(i + 1001, sp));
}
}
这里我采用12星座作为选手名,给定编号,这里是顺序的,等下会打乱
使用make_pair插入map的对组元素
void SpeechContestManager::StartSpeech()
{
this->SpeechLot();//抽签
this->SpeechContest();//比赛
this->ShowScore();//展示成绩
this->m_round++;//进入下一轮
this->SpeechLot();//抽签
this->SpeechContest();//比赛
this->ShowScore();//展示成绩
this->SaveRecord();//保存三甲
this->InitSpeech();//初始化,为下一届做准备
this->CreatSpeaker();
this->LoadRecord();//载入保存记录
cout << "本届比赛结束!" << endl;
system("pause");
system("cls");
}
这里是比赛流程函数的调用
void SpeechContestManager::SpeechLot()
{
cout << "第 << " << this->m_round << " >> 轮比赛选手正在抽签" << endl;
cout << "----------------------------" << endl;
cout << "抽签后演讲顺序如下" << endl;
if (this->m_round == 1)
{
random_shuffle(v1.begin(), v1.end());
for (auto it : this->v1)
cout << it << " ";
cout << endl;
}
else
{
random_shuffle(v2.begin(), v2.end());
for (auto it : this->v2)
cout << it << " ";
cout << endl;
}
cout << "----------------------------" << endl;
system("pause");
cout << endl;
}
利用random_shuffle随机打乱容器数据顺序,里面存的是选手编号
void SpeechContestManager::SpeechContest()
{
cout << "::::::::::第" << this->m_round << "轮比赛正式开始:" << "::::::::::" << endl;
multimap<double, int, greater<double>>groupScore;//设置组容器,用内置函数对象进行降序排序,用于取前三
int num = 0;
vector<int>vc;
if (this->m_round == 1)//第一轮
vc = v1;//将v1的随机编号利用重载=赋给vc
else//反之
vc = v2;
for (auto it : vc)
{
num++;
deque<double>d;//利用deque容器存分数
for (int i = 0; i < 10; i++)
{
double score = (rand() % 400 + 601) / 10.f;//设置随机分数
d.push_back(score);
}
sort(d.begin(), d.end());//进行有序排序
d.pop_back();//去掉最高分
d.pop_front();//去掉最低分
double sum = accumulate(d.begin(), d.end(), 0.0f);//累加函数
double avg= sum / (double)d.size();
this->m_speaker[it].m_score[this->m_round - 1] = avg;//将品均分存入参赛人员信息中
groupScore.insert(make_pair(avg, it));//插入数据
if (num % 6 == 0)//满六人后展示六人成绩
{
cout << "第" << num / 6 << "小组比赛名次:" << endl;
for (auto it : groupScore)
cout << "编号:" << it.second << "\t姓名:" << this->m_speaker[it.second].m_name << "\t成绩" <<fixed<<setprecision(2)<< this->m_speaker[it.second].m_score[this->m_round - 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_round == 1)//为第一轮
v2.push_back(it->second);//存入第二轮
else
v_victory.push_back(it->second);//为第二轮,存入胜利者中
}//这里是将前三的人相应容器中
groupScore.clear();清空
cout << endl;
}
}
cout << "::::::::::第" << this->m_round << "轮比赛结束:" << ":::::::::::" << endl;
system("pause");
}
进行比赛要分第一轮和第二轮进行不同存储
void SpeechContestManager::ShowScore()
{
cout << "::::::::::第" << this->m_round << "轮晋级选手信息如下:" << "::::::::::" << endl;
vector<int>v;
if (this->m_round == 1)
v = v2;
else
v = v_victory;
for (auto it : v)
cout << "选手编号:" << it << "\t姓名:" << m_speaker[it].m_name << "\t得分:" << fixed << setprecision(2) << m_speaker[it].m_score[this->m_round - 1] << endl;
cout << endl;
system("pause");
system("cls");
this->Menu();
}
展示的都是晋级成功的或获胜的人的信息,打印比赛后所存储的信息
void SpeechContestManager::SaveRecord()
{
ofstream out;
out.open(FILENAME, ios::out | ios::app);
for (auto it : v_victory)
out << m_speaker[it].m_name << "," <<fixed<<setprecision(2)<< m_speaker[it].m_score[1] << it << ",";
out << endl;
cout << "记录保存成功" << endl;
this->emptyfile = false;
}
保存本届获胜者信息,用’,'分隔,ios::app追加写入
这里有个问题,无法以两位精度保存数据,不知如何解决
void SpeechContestManager::LoadRecord()
{
ifstream in(FILENAME, ios::in);
if (!in.is_open())
{
this->emptyfile = true;
cout << "文件不存在!" << endl;
in.close();
return;
}
char ch;
in >> ch;
if (in.eof())
{
this->emptyfile = true;
cout << "文件为空!" << endl;
in.close();
return;
}
this->emptyfile = false;
in.putback(ch);
string data;
int index = 0;
while (in >> data)
{
vector<string>v;
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->m_record.insert(make_pair(index, v));
index++;
}
in.close();
}
用is_open()判断文件是否打开
在读出最后一个字符时,in.eof()还是为假的,只当读过最后一个字符再读(读不成功)时in.eof()才变为真,用来判断文件是否为空,读完后用putback()再放回去,如果文件存在且不为空,那么就将数据存入map容器中。
这里先找到’,‘位置,再用子串截取从start到’,'所在下标的子串。更新start获取新数据。
这里是为了应用find()查找函数,实际可以用几个临时变量存取,采用空格隔开。
void SpeechContestManager::ShowRecord()
{
if (this->emptyfile)
cout << "文件不存在或记录为空!" << endl;
else
{
for (int i = 0; i < this->m_record.size(); i++)
{
cout << "第" << i + 1 << "届" <<
"冠军:" << this->m_record[i][0] << "\t得分:" << fixed << setprecision(2) << this->m_record[i][1] << "\t"
"亚军:" << this->m_record[i][2] << "\t得分:" << fixed << setprecision(2) << this->m_record[i][3] << "\t"
"季军:" << this->m_record[i][4] <<"\t得分:" << fixed << setprecision(2) << this->m_record[i][5] << endl;
}
}
system("pause");
system("cls");
}
使用了map容器得[]访问方法,因数据是以greater<>排序过的,所以按顺序输出三甲即可,这里用emptyfile判断文件是否为空。
void SpeechContestManager::ClearRecord()
{
cout << "确认清空?(Y/N)" << endl;
char choice;
cin >> choice;
if (choice == 'Y')
{
ofstream out(FILENAME, ios::trunc);
out.close();
this->InitSpeech();
this->CreatSpeaker();
cout << "清空成功!" << endl;
}
system("pause");
system("cls");
}
使用ios::trunc清除文件数据
通过之前的学习,我们知道,容器内部会自己析构释放内存,这里无需实现任何功能SpeechContestManager::~SpeechContestManager() {};
#include "SpeechcontestManager.h"
SpeechContestManager::SpeechContestManager()
{
this->InitSpeech();
}
void SpeechContestManager::Menu()
{
cout << "********************************************" << endl;
cout << "********* 欢迎参加演讲比赛 *********" << endl;
cout << "********* 1.开始演讲比赛 *********" << endl;
cout << "********* 2.查看往期记录 *********" << endl;
cout << "********* 3.清空比赛记录 *********" << endl;
cout << "********* 0.退出比赛程序 *********" << endl;
cout << "********************************************" << endl;
cout << endl;
}
void SpeechContestManager::Exit()
{
cout << "欢迎下次使用!" << endl;
system("pause");
exit(0);
}
void SpeechContestManager::InitSpeech()
{
this->v1.clear();
this->v2.clear();
this->v_victory.clear();
this->m_speaker.clear();
this->m_record.clear();
this->m_round =1;
}
void SpeechContestManager::CreatSpeaker()
{
string nameSeed[12] = { { "白羊" },{"金牛"},{"双子"},{"巨蟹"},{"狮子"},{"处女"}
,{"天秤"},{"天蝎"},{"射手"},{"摩羯"},{"水瓶"},{"双鱼"} };
for (int i = 0; i < 12; i++)
{
Speaker sp;
sp.m_name = nameSeed[i];
for (int j = 0; j < 2; j++)
sp.m_score[j] = 0;
this->v1.push_back(i + 1001);
this->m_speaker.insert(make_pair(i + 1001, sp));
}
}
void SpeechContestManager::StartSpeech()
{
this->SpeechLot();
this->SpeechContest();
this->ShowScore();
this->m_round++;
this->SpeechLot();
this->SpeechContest();
this->ShowScore();
this->SaveRecord();
this->InitSpeech();
this->CreatSpeaker();
this->LoadRecord();
cout << "本届比赛结束!" << endl;
system("pause");
system("cls");
}
void SpeechContestManager::SpeechLot()
{
cout << "第 << " << this->m_round << " >> 轮比赛选手正在抽签" << endl;
cout << "----------------------------" << endl;
cout << "抽签后演讲顺序如下" << endl;
if (this->m_round == 1)
{
random_shuffle(v1.begin(), v1.end());
for (auto it : this->v1)
cout << it << " ";
cout << endl;
}
else
{
random_shuffle(v2.begin(), v2.end());
for (auto it : this->v2)
cout << it << " ";
cout << endl;
}
cout << "----------------------------" << endl;
system("pause");
cout << endl;
}
void SpeechContestManager::SpeechContest()
{
cout << "::::::::::第" << this->m_round << "轮比赛正式开始:" << "::::::::::" << endl;
multimap<double, int, greater<double>>groupScore;
int num = 0;
vector<int>vc;
if (this->m_round == 1)
vc = v1;
else
vc = v2;
for (auto it : vc)
{
num++;
deque<double>d;
for (int i = 0; i < 10; i++)
{
double score = (rand() % 400 + 601) / 10.f;
d.push_back(score);
}
sort(d.begin(), d.end());
d.pop_back();
d.pop_front();
double sum = accumulate(d.begin(), d.end(), 0.0f);
double avg= sum / (double)d.size();
this->m_speaker[it].m_score[this->m_round - 1] = avg;
groupScore.insert(make_pair(avg, it));
if (num % 6 == 0)
{
cout << "第" << num / 6 << "小组比赛名次:" << endl;
for (auto it : groupScore)
cout << "编号:" << it.second << "\t姓名:" << this->m_speaker[it.second].m_name << "\t成绩" <<fixed<<setprecision(2)<< this->m_speaker[it.second].m_score[this->m_round - 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_round == 1)
v2.push_back(it->second);
else
v_victory.push_back(it->second);
}
groupScore.clear();
cout << endl;
}
}
cout << "::::::::::第" << this->m_round << "轮比赛结束:" << ":::::::::::" << endl;
system("pause");
}
void SpeechContestManager::ShowScore()
{
cout << "::::::::::第" << this->m_round << "轮晋级选手信息如下:" << "::::::::::" << endl;
vector<int>v;
if (this->m_round == 1)
v = v2;
else
v = v_victory;
for (auto it : v)
cout << "选手编号:" << it << "\t姓名:" << m_speaker[it].m_name << "\t得分:" << fixed << setprecision(2) << m_speaker[it].m_score[this->m_round - 1] << endl;
cout << endl;
system("pause");
system("cls");
this->Menu();
}
void SpeechContestManager::SaveRecord()
{
ofstream out;
out.open(FILENAME, ios::out | ios::app);
for (auto it : v_victory)
out << m_speaker[it].m_name << "," <<fixed<<setprecision(2)<< m_speaker[it].m_score[1] << it << ",";
out << endl;
cout << "记录保存成功" << endl;
this->emptyfile = false;
}
void SpeechContestManager::LoadRecord()
{
ifstream in(FILENAME, ios::in);
if (!in.is_open())
{
this->emptyfile = true;
cout << "文件不存在!" << endl;
in.close();
return;
}
char ch;
in >> ch;
if (in.eof())
{
this->emptyfile = true;
cout << "文件为空!" << endl;
in.close();
return;
}
this->emptyfile = false;
in.putback(ch);
string data;
int index = 0;
while (in >> data)
{
vector<string>v;
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->m_record.insert(make_pair(index, v));
index++;
}
in.close();
}
void SpeechContestManager::ShowRecord()
{
if (this->emptyfile)
cout << "文件不存在或记录为空!" << endl;
else
{
for (int i = 0; i < this->m_record.size(); i++)
{
cout << "第" << i + 1 << "届" <<
"冠军:" << this->m_record[i][0] << "\t得分:" << fixed << setprecision(2) << this->m_record[i][1] << "\t"
"亚军:" << this->m_record[i][2] << "\t得分:" << fixed << setprecision(2) << this->m_record[i][3] << "\t"
"季军:" << this->m_record[i][4] <<"\t得分:" << fixed << setprecision(2) << this->m_record[i][5] << endl;
}
}
system("pause");
system("cls");
}
void SpeechContestManager::ClearRecord()
{
cout << "确认清空?(Y/N)" << endl;
char choice;
cin >> choice;
if (choice == 'Y')
{
ofstream out(FILENAME, ios::trunc);
out.close();
this->InitSpeech();
this->CreatSpeaker();
cout << "清空成功!" << endl;
}
system("pause");
system("cls");
}
SpeechContestManager::~SpeechContestManager() {};