这个系统的四个功能:开始演讲比赛、查看往届记录、清空比赛记录、退出比赛程序已经实现了两个了,其中开始演讲比赛已经在上一篇实现了,接下是查看往届记录。
实现步骤:
void loadRecord();
bool fileIsEmpty;
map> m_Record;
void loadRecord();
这一块,分两部分,一是判断文件情况,并且是否能成功读取文件数据,二是读取文件有效信息,并放进往届记录的容器map
中用于后面的查看记录功能的实现。
一、文件情况判断
//读取记录void loadRecord();//文件为空的标志bool fileIsEmpty;//往届记录map> m_Record;
//查看往届记录
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;//csv文件中每一行的所有字符串while (ifs >> data){cout << data << endl;}ifs.close();}
注意点:
!ifs.is_open()
判断文件是否存在。如果不存在提示用户并关闭文件,并且把文件为空的标志设置为真,this->FileIsEmpty = true;
ifs.eof()
判断。如果文件为空,提示用户并关闭文件,并且把文件为空的标志设置为真,this->FileIsEmpty = true;
this->FileIsEmpty = false;
。在前面判断文件是否为空时,已经读取了一个字符,为了保证信息完整,需要把这个字符放回去,ifs.putback(ch);
最后在基于SCL的演讲比赛流程管理系统.cpp中调用成员函数 void loadRecord();
查看是否读到数据
效果:
二、读取文件有效信息
map> m_Record;
的vector
容器中。//构造函数
SpeechManager::SpeechManager()
{//成员属性初始化this->initSpeech();//创建12名选手this->createSpeaker();//加载往届记录this->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;//csv文件中 每一行的所有字符串int index = 1;while (ifs >> data){//cout << data << endl;//data:10002,86.675,10009,81.3,10007,78.55,int pos = -1;//查找到“,”的位置变量 find返回值int start = 0;//查找的起始位置 find起始查找位置vector v;while (1){pos = data.find(",", start);if (pos == -1){//没有找到break;}string temp = data.substr(start, pos - start);//起始位置 截取长度v.push_back(temp);//cout << temp << endl;start = pos + 1;//找下一个有效字符串的起始位置}//存在记录容器中 index第几届 v前三名成绩和编号this->m_Record.insert(make_pair(index, v));index++;}m_Record是否存放正确测试//for (map>::iterator it = m_Record.begin(); it != m_Record.end(); it++)//{// cout << "第 " << it->first << " 届\t" << "冠军编号:" << it->second[0] << "\t冠军成绩:" << it->second[1] << endl;//}ifs.close();
}
解释:
我们直到信息是data:10002,86.675,10009,81.3,10007,78.55, 这样的,以下解释如何有效截取的思路
int start = 0;
。int pos = -1;
。start
,长度则是起始位置到第一个逗号的位置,即pos - start
。再把substr截取有效字符放入vector v;
中。start
需要更新,每次截取一个有效字符后都应该从当前逗号的位置开始,即start = pos + 1;
,再重复以上操作。int index = 1;
,每往m_Record存一次数据,index+1,表示下一届。实现步骤:
void showRecord();
void showRecord();
代码展示:
此前已经把选手信息存入m_Record容器中了,接下来只需要正确读取容器的数据并打印即可
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");
}
在基于SCL的演讲比赛流程管理系统.cpp中实现成员函数 void showRecord();
,在main函数分支 2 选项中,调用查看记录的接口
目前程序中有几处bug未解决:
解决方式: 在showRecord函数中,开始判断文件状态并加以判断
//显示往届记录
void SpeechManager::showRecord()
{if (this->FileIsEmpty){cout << "文件不存在或文件为空!" << endl;}else{for (int i = 1; i <= this->m_Record.size(); i++){cout << "第" << i << "届" << "\t冠军编号:" << this->m_Record[i][0] << " 成绩:" << this->m_Record[i][1]<< "\t\t亚军编号:" << this->m_Record[i][0] << " 成绩:" << this->m_Record[i][1] << "\t\t季军编号:" << this->m_Record[i][0] << " 成绩:" << this->m_Record[i][1] << endl;}}system("pause");system("cls");
}
解决方式: 在saveRecord中更新文件为空的标志
3. 比完赛后查不到本届比赛的记录,没有实时更新
解决方式: 比赛完毕后,所有数据重置。在startSpeech函数中,再次重置比赛
4. 在初始化时,没有初始化记录容器
解决方式: initSpeech中添加初始化记录容器
5. 每次记录都是一样的
解决方式: 在基于SCL的演讲比赛流程管理系统.cpp的main函数一开始添加随机数种子