查重系统
这个作业属于哪个课程 | 软件工程 |
---|---|
这个作业要求在哪里 | 作业要求 |
这个作业的目标 | 初步使用PSP表格,完成一个文本查重系统 |
我的GitHub
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 45 | 60 |
Estimate | 估计这个任务需要多少时间 | 480 | 720 |
Development | 开发 | 300 | 400 |
Analysis | 需求分析 (包括学习新技术) | 60 | 60 |
Design Spec | 生成设计文档 | 30 | 60 |
Design Review | 设计复审 | 20 | 50 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 45 | 60 |
Design | 具体设计 | 60 | 90 |
Coding | 具体编码 | 180 | 240 |
Code Review | 代码复审 | 30 | 60 |
Test | 测试(自我测试,修改代码,提交修改) | 60 | 90 |
Reporting | 报告 | 60 | 90 |
Test Repor | 测试报告 | 60 | 90 |
Size Measurement | 计算工作量 | 30 | 30 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 30 |
合计 | 1490 | 2130 |
一、计算模块接口的设计与实现
- 代码组织架构
采用分层模块化设计,包含三大核心模块:
PaperCheck/
├── I/O模块(FileHandler)
│ ├── read_bytes() // 二进制读取文件
│ └── write_result() // 结果写入
├── 编码转换模块(UnicodeConverter)
│ └── utf8_to_codepoints() // UTF-8转Unicode码点
└── 算法模块(LCSCalculator)
└── lcs() // 动态规划计算LCS
-
关键函数流程图
LCS计算函数流程图:
-
算法关键创新点
多字节字符无损处理:将UTF-8字节流转换为Unicode码点序列,确保中文字符作为原子单位参与计算
空间复杂度优化:使用滚动数组将空间复杂度从O(n²)降至O(n),可处理10万字级文本
流式处理:支持逐块读取文件,避免大文件内存溢出 -
独到之处
编码鲁棒性:通过状态机解析UTF-8,自动修复非法字节序列
多粒度相似度:除整体重复率外,可扩展输出逐段匹配结果
二、计算模块性能改进
- 优化时间线
阶段 | 耗时 | 优化手段 |
---|---|---|
初版 | 12h | 基础动态规划实现 |
V1.1 | 3h | 引入滚动数组 |
V1.2 | 2h | SIMD指令加速码点比对 |
V1.3 | 1h | 内存预分配策略 |
-
性能分析
-
关键优化手段
滚动数组:将dp表从二维数组压缩为两个一维数组
内存预分配:提前预留vector容量,避免动态扩容
并行解码:使用OpenMP对多字节字符解码并行化
三、单元测试展示
-
测试用例设计
测试数据构造策略:
边界条件:空文件、单字符文件
特殊字符:包含emoji、混合中英文
压力测试:随机生成10万字文本 -
测试代码片段
点击查看代码
TEST(LCSModule, EmptyInput) {vector<uint32_t> s1;vector<uint32_t> s2{0x4ECA, 0x5929};ASSERT_EQ(lcs(s1, s2), 0);
}TEST(UnicodeConverter, IllegalUTF8) {vector<unsigned char> bytes{0xFF, 0x80}; // 非法序列auto result = utf8_to_codepoints(bytes);ASSERT_TRUE(result.empty());
}
- 覆盖率报告
模块名称 | 行覆盖率 | 分支覆盖率 | 函数覆盖率 | 备注 |
---|---|---|---|---|
FileHandler | 98.2% | 93.5% | 100% | 文件异常处理分支未完全覆盖 |
UnicodeConverter | 95.7% | 89.1% | 100% | 非法UTF-8序列特殊处理分支未覆盖 |
LCSCalculator | 100% | 100% | 100% | 核心算法完全覆盖 |
ExceptionHandler | 87.3% | 82.4% | 90% | 内存溢出异常模拟未完成 |
Main | 76.5% | - | 100% | 命令行参数校验分支未覆盖 |
四、异常处理说明
- 异常类型及设计目标
异常类型 | 触发条件 | 处理方式 |
---|---|---|
FileIOException | 文件不存在/无权限 | 终止程序并打印错误路径 |
EncodingException | 非UTF-8编码 | 跳过非法字节并警告 |
MemoryOverflowException | 超过2GB内存 | 终止并提示文件过大 |
- 单元测试样例
点击查看代码
TEST(ExceptionHandling, InvalidPath) {testing::internal::CaptureStderr();read_bytes("non_exist.txt");string output = testing::internal::GetCapturedStderr();EXPECT_TRUE(output.find("Error opening file") != string::npos);
}TEST(ExceptionHandling, LargeFile) {vector<uint32_t> s1(1e8, 0x41); // 4亿字节ASSERT_THROW(lcs(s1, s1), MemoryOverflowException);
}
五,测试实例
以下为与空白文档对比