688
社区成员
发帖
与我相关
我的任务
分享| 这个作业属于哪个课程 | https://bbs.csdn.net/forums/weixin_53785144-01 |
|---|---|
| 这个作业要求在哪里 | https://bbs.csdn.net/topics/613505605 |
| 这个作业的目标 | 完成对澳大利亚网球公开赛相关数据的收集,并实现一个能够对赛事数据进行统计的控制台程序 |
| 其他参考文献 | CSDN 、Github |
| PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 30 | 20 |
| Estimate | 估计这个任务需要多少时间 | 100 | 130 |
| Development | 开发 | 10 | 30 |
| Analysis | 需求分析 | 40 | 30 |
| Design Spec | 生成设计文档 | 30 | 30 |
| Design Review | • 设计复审 | 20 | 20 |
| Coding Standard | • 代码规范 | 25 | 30 |
| Design | • 具体设计 | 30 | 40 |
| Coding | • 具体编码 | 60 | 70 |
| Code Review | • 代码复审 | 20 | 50 |
| Test | • 测试 | 30 | 30 |
| Reporting | 报告 | 30 | 35 |
| Test Repor | • 测试报告 | 20 | 20 |
| Size Measurement | • 计算工作量 | 30 | 50 |
| Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 30 | 35 |
| 合计 | 505 | 620 |
我们需要将澳洲网球公开赛的所有比赛信息包括选手和比赛结果信息当获得相应的信息时,输出给output.txt中。我们获得的数据主要来源于json数据,而有关json数据,一部分通过助教在群里分享,另一部分通过edge的F12中获得json数据
一开始时通过jsoncpp进行数据解析,但是在性能优化的时候,jsoncpp性能过低,后面改用rapidjson进行解析json数据
代码主要是分为两部分,一部分工具代码(Lib.h,Lib.cpp),另一部分就是主程序(AOSearch.cpp),以下时Lib.h的展现。其中把基本功能里的:1、输出所有选手信息,2、输出每日比赛结果,都封装成方法进行调用。

1、通过四重循环,获得result中获胜人员,比赛场次,以及开始时间的信息
void Lib::FindJson2(string filename) {
string path;
if (filename.find("result") != string::npos) {
int pos = filename.find("result");
filename.erase(pos, 6);
filename.erase(remove(filename.begin(), filename.end(), ' '), filename.end());
// cout << filename<<endl;
path = "src/data/" + filename+".json";
string dataFromJson;
ifstream in(path, ifstream::in);
if (in.is_open()) {
string line;
while (getline(in, line))
{
dataFromJson.append(line + "\n");
}
}
else {
datas.push_back("N/A");
datas.push_back("-----");
}
rapidjson::Document d;
d.Parse(dataFromJson.c_str());
rapidjson::Value& courts = d["schedule"]["courts"];
string team_id;//获胜队伍的id
string player_id1 = "";//第一位获胜个人的id
string player_id2 = "";//第二位获胜个人的id
string winner_name = "";//获胜者信息
for (auto &court : courts.GetArray()) {
for (auto& session : court["sessions"].GetArray()) {
for (auto& activity : session["activities"].GetArray()) {
if (!activity.HasMember("teams")) break;
string abbr = activity["match_status"]["abbr"].GetString();
if ( abbr._Equal("W/O")) {
datas.push_back("W/O");
datas.push_back("-----");
break;
}
string start_time = activity["actual_start_time"].GetString();
// cout << start_time << endl;
datas.push_back("time:" + start_time);
auto& teams = activity["teams"]; // root/schedule/courts/sessions/activities/teams
// cout << teams[0]["team_id"] << endl << teams[1]["team_id"] << endl;
auto &team = teams[0];
if (team.HasMember("status"))
{
team_id = teams[0]["team_id"].GetString();
}
else { team_id = teams[1]["team_id"].GetString(); }
for (auto &Team : d["teams"].GetArray()) {
if (Team["uuid"].GetString() == team_id)
{
if (Team["players"].GetArray().Size() == 1)
{
player_id1 = Team["players"][0].GetString();
break;
}
else {
player_id1 = Team["players"][0].GetString();
player_id2 = Team["players"][1].GetString();
break;
}
}
}
for (auto &player : d["players"].GetArray())
{
if (player["uuid"].GetString() == player_id1 || player["uuid"].GetString() == player_id2) {
if (player_id2 == "")
{
// cout << player["short_name"].asString() << endl;
string short_name = player["short_name"].GetString();
datas.push_back("winner:" + short_name);
winner_name = "";
break;
}
else {
if (winner_name == "")
{
string short_name = player["short_name"].GetString();
datas.push_back("winner:" + short_name);
winner_name += "winner:" + short_name + " & ";
}
else {
winner_name += player["short_name"].GetString();
// cout << winner_name << endl;
datas.push_back(winner_name);
winner_name = "";
break;
}
}
}
}
string scores = "score:";//分数
int times = teams[0]["score"].GetArray().Size();
for (int i = 0; i < times; i++) {
string score1 = teams[0]["score"][i]["game"].GetString();
string score2 = teams[1]["score"][i]["game"].GetString();
scores += " " + score1 + ":" + score2 + " ";
if (i < times - 1) {
scores += "|";
}
}
// cout << scores << endl;
datas.push_back(scores);
datas.push_back("-----");
}
}
}
}
else {
datas.push_back("Error");
datas.push_back("-----");
}
}
2、打开players的数据,直接读取所有成员的有关数据
void Lib::FindJson(string filename) {
string path = "src/data/" + filename + ".json";
string dataFromJson;
ifstream in(path,ifstream::in);
if (in.is_open()) {
string line;
while (getline(in,line))
{
dataFromJson.append(line + "\n");
}
}
else {
cout << "打开失败" << endl;
}
rapidjson::Document d;
d.Parse(dataFromJson.c_str());
rapidjson::Value& players = d["players"];
for (unsigned int i = 0; i < players.Size(); i++) {
string name = players[i]["full_name"].GetString();
datas.push_back("full_name:" + name);
rapidjson::Value::ConstMemberIterator gender = players[i].FindMember("gender");
string G = gender->value.GetString();
if (G._Equal("M")) {
datas.push_back("gender: male");
}
else
{
datas.push_back("gender: female");
}
rapidjson::Value& nationality = players[i]["nationality"];
string nationality_name=nationality["name"].GetString();
datas.push_back("nationlity:"+nationality_name);
datas.push_back("-----");
}
}
3、 将解析出来的数据存入目标文件,如output.txt中
//将解析出来的json的数据写入文件中
void Lib::writeFile(string file,list<string> datas) {
ofstream f(this->output,ios::out);
if (!f.is_open()) {
cout << "文件查找不到" << endl;
return;
}
for (list<string>::iterator it = datas.begin(); it != datas.end(); ++it) {
f<< *it << "\n";
}
f.close();
}
4、通过input.txt文件中的信息,将每行的内容读入list 中,随后一次解析每行文件的json数据
list <string> Lib::readFile(string file) {
list <string> data; //获得解析input内的数据
ifstream f(file, ios::in);
if (!f.is_open()) {
cout << "文件打开失败" << endl;
return data;
}
string strline;
/*do
{
getline(f, strline);
data.push_back(strline);
}while (getline(f, strline));*/
while (getline(f, strline)) {
data.push_back(strline);
}
f.close(); //关闭文件输入流
return data;
}
5、通过从文件list获得的数据,一次分配到不同的FindJson中,进行json数据解析
void Lib::getData(list <string> data) {
for (list<string>::iterator it = data.begin(); it != data.end(); ++it) {
if (*it == "players")
{
FindJson("players");
}
else {
string s = *it;
FindJson2(s);
}
}
}
一开始使用jsoncpp的库进行数据解析,结果发现每次要调用解析json的方法的时候,都要进入文件夹,调用dll的相关方法,导致每次都要花大量的读取时间,

之后在对网络上进行查询有无更简单的优化方法时,找到了rapidjson的库,只需要将rapidjson中的include/rapidjson放入文件夹中,便能够调用有关的方法,之后便是修改FindJson方法(获得players的json数据)

发现性能有极大的优化以后,我们便修改了关于解析result的FindJson方法

极大的减少了时间的花费
对于单元测试,我们需要使用vs2022自带的GoogleTest框架进行测试,虽然在这过程中,对于GoogleTest的使用我是一窍不通,但是通过查阅相关的文档和有关资料,我马马虎虎学习了对GoogleTest的使用,然后可能用的不够完美。

对于异常的处理,主要情况都是文件无法找到从而难以打开,而处理方法是直接抛出
//json数据打不开
if (in.is_open()) {
string line;
while (getline(in,line))
{
dataFromJson.append(line + "\n");
}
}
else {
cout << "打开失败" << endl;
}
//文件input.txt打不开
list <string> data; //获得解析input内的数据
ifstream f(file, ios::in);
if (!f.is_open()) {
cout << "文件打开失败" << endl;
return data;
}
1、通过这次的学习,了解了c++使用json的方法,复习了c++的相关知识。
2、在进行jsoncpp和GoogleTest时候的耗时是最久的,其中jsoncpp是使用cmake将从Github下载下来的zip解析并且生成解决方法,获得dll文件后添加到项目工程下,其次最令我头疼的就是就是关于GoogleTest的使用,我还特意重新建了一个SampleTest文件,进行测试,因此进行的有点困难
3、最后最大的收获,便是更加了解了git的使用方法,对于开发的流程有了更加熟悉的认知
性能改进部分很有亮点,赞!