C++ 演讲比赛流程管理系统(五)查看往届记录功能的具体实现:读取分数、查看记录、测试、bug解决
创始人
2025-05-31 03:55:29
0

2、 查看往届记录

这个系统的四个功能:开始演讲比赛、查看往届记录、清空比赛记录、退出比赛程序已经实现了两个了,其中开始演讲比赛已经在上一篇实现了,接下是查看往届记录。

2.1 读取记录分数

实现步骤:

  • 在speechManager.h中添加保存记录的成员函数 void loadRecord();
  • 添加判断文件是否为空的标志 bool fileIsEmpty;
  • 添加往届记录的容器map> m_Record;
  • 其中m_Record 中的key代表第几届,value记录具体的信息,包括选手的编号和成绩
  • 在speechManager.cpp中实现成员函数 void loadRecord();

这一块,分两部分,一是判断文件情况,并且是否能成功读取文件数据,二是读取文件有效信息,并放进往届记录的容器map> m_Record; 中用于后面的查看记录功能的实现。

一、文件情况判断

  1. speechManager.h中
	//读取记录void loadRecord();//文件为空的标志bool fileIsEmpty;//往届记录map> m_Record;
  1. speechManager.cpp中
//查看往届记录
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();}

注意点:

  1. 后续优化可以把文件名speech.csv写成宏常量,防止写错文件名
  2. 读取比赛往届分数时,分为三种情况,分别是文件不存在、文件存在但文件为空、文件不为空:
  • 文件不存在:首先打开文件,通过!ifs.is_open()判断文件是否存在。如果不存在提示用户并关闭文件,并且把文件为空的标志设置为真,this->FileIsEmpty = true;
  • 文件为空:首先读一个字符,如果文件为空,那么这个字符是光标字符,通过ifs.eof()判断。如果文件为空,提示用户并关闭文件,并且把文件为空的标志设置为真,this->FileIsEmpty = true;
  • 文件不为空:首先需要把文件为空的标志设置为假,this->FileIsEmpty = false;。在前面判断文件是否为空时,已经读取了一个字符,为了保证信息完整,需要把这个字符放回去,ifs.putback(ch);
  • 再用一个string容器来接收每一行的信息,这里先读文件第一行的所有字符串,并输出显示是否读取成功。

最后在基于SCL的演讲比赛流程管理系统.cpp中调用成员函数 void loadRecord();查看是否读到数据
在这里插入图片描述
效果:
在这里插入图片描述
二、读取文件有效信息

  1. 在上面已经成功读取了信息,接下来需要根据逗号,把每个数字都读出来,截取有效信息,放在往届记录的容器map> m_Record;vector容器中。
  2. 记录往届成绩的文件应该在比赛开始前就加载,所以在speechManager.cpp的构造函数中调用查看往届记录函数,在main函数就不需要另外加载了。
//构造函数
SpeechManager::SpeechManager()
{//成员属性初始化this->initSpeech();//创建12名选手this->createSpeaker();//加载往届记录this->loadRecord();
}
  1. 利用string的特点,通过查找逗号的位置和substr截取有效字符串。查看往届记录功能完整代码,如下:
//查看往届记录
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, 这样的,以下解释如何有效截取的思路

  1. 首先,根据find函数的参数,需要查找的起始位置,那么最初的查找逗号起始位置是在0,即int start = 0;
  2. find无论找到与否都有一个int返回值,用一个变量来接收,这个变量表示的是逗号所在位置,并且初始化这个变量为-1,表示假设没有找到逗号,int pos = -1;
  3. 通过pos的值来判断是否找到逗号,如果pos=-1,说明没有找到,否则找到逗号
  4. 找到逗号后,通过substr来截取有效字符。就以10002来说,起始截取位置是起始位置0索引start,长度则是起始位置到第一个逗号的位置,即pos - start。再把substr截取有效字符放入vector v;中。
  5. 为了继续截取下一个有效字符,通过一个循环来重复截取data的有效信息。但是start需要更新,每次截取一个有效字符后都应该从当前逗号的位置开始,即start = pos + 1;,再重复以上操作。
  6. 所有有效字符都截取后,再存入 m_Record中。key对应的是第几届比赛,value则是当届比赛的选手信息。初始化一个变量来控制比赛的届数,int index = 1;,每往m_Record存一次数据,index+1,表示下一届。
  7. 最后可以测试是否都正确保存选手信息在m_Record容器中。

2.2 查看记录功能

实现步骤:

  • 在speechManager.h中添加保存记录的成员函数 void showRecord();
  • 在speechManager.cpp中实现成员函数 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");
}

2.3 测试功能

在基于SCL的演讲比赛流程管理系统.cpp中实现成员函数 void showRecord();,在main函数分支 2 选项中,调用查看记录的接口
在这里插入图片描述
在这里插入图片描述

2.4 bug解决

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

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

解决方式: 在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");
}
  1. 若记录为空或不存在,比完赛后依然提示记录为空

解决方式: 在saveRecord中更新文件为空的标志
在这里插入图片描述
3. 比完赛后查不到本届比赛的记录,没有实时更新

解决方式: 比赛完毕后,所有数据重置。在startSpeech函数中,再次重置比赛

在这里插入图片描述
4. 在初始化时,没有初始化记录容器

解决方式: initSpeech中添加初始化记录容器
在这里插入图片描述
5. 每次记录都是一样的

解决方式: 在基于SCL的演讲比赛流程管理系统.cpp的main函数一开始添加随机数种子
在这里插入图片描述

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
JAVA多线程知识整理 Java多线程基础 线程的创建和启动 继承Thread类来创建并启动 自定义Thread类的子类&#...
【洛谷 P1090】[NOIP... [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G ...
国民技术LPUART介绍 低功耗通用异步接收器(LPUART) 简介 低功耗通用异步收发器...
城乡供水一体化平台-助力乡村振... 城乡供水一体化管理系统建设方案 城乡供水一体化管理系统是运用云计算、大数据等信息化手段࿰...
程序的循环结构和random库...   第三个参数就是步长     引入文件时记得指明字符格式,否则读入不了 ...
中国版ChatGPT在哪些方面... 目录 一、中国巨大的市场需求 二、中国企业加速创新 三、中国的人工智能发展 四、企业愿景的推进 五、...
报名开启 | 共赴一场 Flu... 2023 年 1 月 25 日,Flutter Forward 大会在肯尼亚首都内罗毕...
汇编00-MASM 和 Vis... Qt源码解析 索引 汇编逆向--- MASM 和 Visual Studio入门 前提知识ÿ...
【简陋Web应用3】实现人脸比... 文章目录🍉 前情提要🌷 效果演示🥝 实现过程1. u...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
windows安装JDK步骤 一、 下载JDK安装包 下载地址:https://www.oracle.com/jav...
分治法实现合并排序(归并排序)... 🎊【数据结构与算法】专题正在持续更新中,各种数据结构的创建原理与运用✨...
在linux上安装配置node... 目录前言1,关于nodejs2,配置环境变量3,总结 前言...
Linux学习之端口、网络协议... 端口:设备与外界通讯交流的出口 网络协议:   网络协议是指计算机通信网...
Linux内核进程管理并发同步... 并发同步并发 是指在某一时间段内能够处理多个任务的能力,而 并行 是指同一时间能够处理...
opencv学习-HOG LO... 目录1. HOG(Histogram of Oriented Gradients,方向梯度直方图)1...
EEG微状态的功能意义 导读大脑的瞬时全局功能状态反映在其电场结构上。聚类分析方法一致地提取了四种头表面脑电场结构ÿ...
【Unity 手写PBR】Bu... 写在前面 前期积累: GAMES101作业7提高-实现微表面模型你需要了解的知识 【技...