软件工程第二次作业--文件读取

222100326郑锦程 2024-03-02 23:44:16
这个作业属于哪个课程2302软件工程
这个作业要求在哪里软件工程第二次作业--文件读取
这个作业的目标完成对数据项目的抓取
其他参考文献《构建之法》、工程师的能力评估和发展单元测试和回归测试Microsoft Visual Studio 文档

目录

  • 1 Gitcode项目地址
  • 2 PSP表格
  • 3 解题思路描述
  • 3.1 具体思路
  • 3.2 数据分析
  • 4 接口设计和实现过程
  • 4.1 结构体
  • 4.2 比较函数
  • 4.3 实用函数
  • 4.4 功能实现函数(计算模块)
  • 4.5 指令读取函数
  • 4.6 程序示意图
  • 5 关键代码展示
  • 6 性能改进
  • 6.1 改进之处
  • 6.2 改进前后对比
  • 7 单元测试
  • 8 异常处理
  • 9 心得体会

1 Gitcode项目地址

2 PSP表格

PSPPersonal Software Process Stages预估耗时(分钟)预估耗时(分钟)
Planning计划4030
• Estimate• 估计这个任务需要多少时间4030
Development开发18002000
• Analysis• 需求分析 (包括学习新技术)150160
• Design Spec• 生成设计文档3040
• Design Review• 设计复审2040
• Coding Standard• 代码规范 (为目前的开发制定合适的规范)1020
• Design• 具体设计3025
• Coding• 具体编码14001550
• Code Review• 代码复审4045
• Test• 测试(自我测试,修改代码,提交修改120130
Reporting报告7070
• Test Repor• 测试报告6060
• Size Measurement• 计算工作量2020
• Postmortem & Process Improvement Plan• 事后总结, 并提出过程改进计划2020
合计19102100

3 解题思路描述

    首先要明白这个项目的目的是什么,其次就是需要实现的功能有哪些。
    当然,在此之前,先要规定一下代码风格,工欲善其事必先利其器。
    前人的经验是很重要的,要求里也提供了往届的优秀作业,于是先去看了一遍,了解了大概过程。在脑海中有一个大致的印象,接下来就是对着作业的功能要求一步步地去完成,这样先总后分,有条不紊。
    以及在完成功能之前要先对json数据进行相应的分析。
    资料大部分当然是在CSDN上寻找了:)

3.1 具体思路

  1. 理解需求: 首先,仔细阅读题目,理解DWASearch的功能要求,包括输出选手信息、比赛结果等。

  2. 分析输入和输出: 将不同指令的输入与输出进行分析,了解各个功能的要求和输出格式,注意处理空格和格式的要求。

  3. 模块设计: 将基本功能拆分,设计类或函数来处理这些功能。

  4. 处理指令: 在程序中添加逻辑,根据输入的指令执行相应的功能模块。

  5. 数据处理: 考虑如何处理爬取的数据,可能需要设计数据结构来存储选手信息和比赛结果。

  6. 异常处理: 实现对错误指令的处理,如无法识别的指令,输出Error。

  7. 性能分析: 进行性能分析,确保程序在处理大量数据时仍能保持高效。

  8. 接口封装: 根据需求,设计模块,将基本功能封装,以便在不同环境中使用。

  9. 单元测试: 设计多个测试用例,确保程序能够正确处理各种情况,包括正常输入和异常情况。

  10. 文档编写: 编写清晰的注释和文档,使其他人能够理解和使用代码。

  11. 定期提交: 按照项目进度,定期提交代码,确保整个项目的稳步推进。

3.2 数据分析

  • 对athletes.json的分析

    athletes.json的解析

  • 对event.json的分析,注意点:项目名称有大写,而作业指令要求全小写

    event

  • 对比赛json的分析

    1


    2


    3


    (对于双人项目)

    4

4 接口设计和实现过程

    首先,功能是关于cmd命令的,要实现这个功能其实主要就是main函数传入的参数设置。我这里遇到了一些问题,最后查csdn博客得知,argv[0]原来固定是程序名...
    接下来考虑第一个功能,players的打印,(Json的爬取在往届作业里已经很详尽了,于是偷懒用现成·),有了Json后呢,如何解析?在网络上找了很多资料,发现了c++上比较好用的Json解析库--nolohmann
    在写识别result和detail指令的时候一直出现out_of_range的报错,换了好几种写法依旧没有办法解决,最后排查是没有考虑特殊情况的原因,特别是当字符串为空,或者字符串只有一个单词时候的情况,花了很多时间去调试才找到这个错误原因...
    开发完功能后就要进行一系列的测试,修复了一堆bug
    到后面还发现players的排序是要stable_sort的
    接下来请欣赏我的程序设计:)

4.1 结构体

  • Score: 用于存储分数信息。
  • Player: 用于存储选手信息。

    结构体示意图

4.2 比较函数

  • cmpPlayers: 用于按照国家和姓氏排序选手。

4.3 实用函数

  • removeLastWord, removeFirstWord, isLastWordDetail, isFirstWordResult, toLowerCase: 提供一些字符串处理和判断功能。

4.4 功能实现函数(计算模块)

  • printPlayers, printResult, printResultDetail: 负责从 JSON 文件读取数据并输出相应信息。
  • getID: 根据事件名称从 event.json 文件中获取对应的事件ID。

4.5 指令读取函数

  • readCommand: 读取指令并根据指令调用相应的打印函数。

4.6 程序示意图

请添加图片描述

5 关键代码展示

主要的关键代码位于打印函数和事件ID获取函数。以下是关键函数的思路和代码示例:

  • printPlayers: 从 JSON 文件读取选手信息,排序后输出。关键之处在于使用了结构体 Player 存储选手信息,并利用 cmpPlayers 函数进行stable_sort排序。

    void printPlayers(std::ofstream& outputFile) {
        // 读取选手信息并存储在 players 向量中
        // 排序选手信息
        // 输出选手信息
    }
    
  • printResult: 从 JSON 文件读取比赛结果并输出选手详情、排名和分数。利用了结构体 Score 存储分数信息。

    void printResult(std::string ID, std::ofstream& outputFile) {
        // 读取比赛结果信息
        // 输出选手信息、排名和分数
    }
    
  • printResultDetail: 从 JSON 文件读取详细比赛结果并输出选手详情、排名和分数。此函数较为复杂,因为需要处理不同比赛轮次和选手的数据。算法的精髓:因为发现Json的比赛顺序从前到后先是决赛再是半决赛最后是初赛,所以从后往前搜到的第一个就是这整个比赛的第一场比赛。

    void printResultDetail(std::string ID, std::ofstream& outputFile) {
        // 读取详细比赛结果信息
        // 处理不同比赛轮次的数据,输出选手详情、排名和分数
    }
    
  • getID: 根据事件名称从 event.json 文件中获取对应的事件ID。

    void getID(std::string name, std::string& ID) {
        // 从 event.json 中读取数据,找到匹配的事件ID
    }
    

6 性能改进

6.1 改进之处

  1. 全局变量:

    • 将选手信息和比赛结果的缓存变量 playersIDToResultMapIDToResultDetailMap 改为全局变量。
    • 通过全局变量,可以避免在每个函数调用时都重新读取选手信息和比赛结果,提高了程序运行效率。
    vector<Player> players;  // 选手信息缓存
    
  2. unordered_map的使用:

    • 利用 unordered_map 存储选手名字到索引和ID到选手数组的映射,在结果的处理中,避免了对数组的多次遍历,减少了搜索时间。
    unordered_map<string, int> nameToPlayer;  // 选手名字到索引的映射
    unordered_map<string, vector<Player>> IDToResultMap;  // ID到结果的选手数组的映射
    unordered_map<string, vector<Player>> IDToResultDetailMap;  // ID到详细结果的选手数组的映射
    
  3. 缓存更新策略:

    • 在每次需要读取选手信息和比赛结果时,先检查缓存中是否已经存在,如果存在则直接使用缓存数据,否则再进行文件读取和数据处理。
    • 这种策略可以有效避免不必要的文件读取操作,提高了程序运行效率。
    if (IDToResultMap.find(ID) == IDToResultMap.end()) {
        // 如果缓存中不存在比赛结果,则进行文件读取和数据处理,并更新缓存
        // ...
    } else {
        // 直接使用缓存中的比赛结果数据
        players = IDToResultMap[ID];
    }
    
  1. 缓存输入输出:
    • 在C++中,使用缓冲流进行文件输入输出是一种高效处理文件数据的方式。C++标准库中的iostream提供了丰富的类和函数,用于控制输入输出(I/O)。对于文件操作,主要涉及到<fstream>头文件中的ifstream(用于文件输入),ofstream(用于文件输出。这些类都支持缓冲操作,意味着它们会将数据暂存于内存中的一个缓冲区,然后批量处理,这样可以减少对磁盘的直接读写次数,从而提高效率。

6.2 改进前后对比

对多次输入同一指令的input

在这里插入图片描述


(ps:总共100行指令,且改进前后都使用缓存输入输出)

改进前:
0.7764s

请添加图片描述

改进后:
0.2822s

请添加图片描述

结论:对上述input,速度快了0.5s左右,快了63.7%左右

7 单元测试

测试用例包含以下情况:

  • 空行存在
  • 项目名称写错或找不到
  • players命令后带参数
  • 命令行参数数量不够
  • 第一个词不是players或result
  • 输入文件找不到
  • players命令格式正确
  • result命令以及带detail的result命令正确格式
  • 项目名和detail之间的空格不仅限于一个
  • 包含其他不必要的空格
  • 最后一个测试是大大大大大样例

请添加图片描述

部分样例展示:

在这里插入图片描述

vs2019覆盖率的查看只有专业版能用(哭腔
一个月250美元的专业版怎么不去抢钱

Microsoft文档

在这里插入图片描述

但是,
没有关系!
我在gittub上面找到了一个免费的插件:FindCodeCoverage

装上以后测覆盖率:

在这里插入图片描述


什么!!怎么50%都不到?

在这里插入图片描述


展开All发现,原来只是引用的库里有一堆代码没用到而已
我编写的代码的覆盖率是94.6%

在这里插入图片描述

为了优化覆盖率,还有以下建议:

  • 重构代码:对于结构复杂、难以测试的代码,考虑进行重构。简化代码逻辑,减少不必要的分支,使代码更容易理解和测试。例如,将复杂函数拆分为多个小函数,使用设计模式来改善代码结构等。

8 异常处理

  1. 命令行参数检查:

    • 使用 argcargv 确保程序接收到正确数量的命令行参数(这里是 3 个参数)。
    • 如果命令行参数不符合要求,输出错误信息并返回错误码 1。
    if (argc != 3) {
        std::cout << "Error on argv.\n";
        return 1;
    }
    
  2. 文件打开异常处理:

    • 在尝试打开输入文件和输出文件时,通过检查文件流对象的状态来确保文件成功打开。
    • 如果文件打开失败,输出相应的错误信息并返回错误码 1。
    if (!inputFile) {
        std::cout << "Failed to open input file.\n";
        return 1;
    }
    if (!outputFile) {
        std::cout << "Failed to open output file.\n";
        return 1;
    }
    

9 心得体会

首先是对git的运用更加熟悉了,其次是对Json解析更加熟悉了,之前有个移动应用开发的课也有解析Json,但是这次更加深刻的了解了一遍。更加重要的是为项目开发算是累积了一些经验,因为走完了完整的开发流程,算是一次非常充分的热身吧!相信这些弥足珍贵的经验会为我的未来计算机之路做出不小的贡献:)

...全文
75 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

122

社区成员

发帖
与我相关
我的任务
社区描述
FZU-SE
软件工程 高校
社区管理员
  • LinQF39
  • 助教-吴可仪
  • 一杯时间
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧