个人项目
| 这个作业属于哪个课程 | 软件工程 |
|---|---|
| 这个作业要求在哪里 | 作业要求 |
| 这个作业的目标 | 学会使用GitHub保存项目,Git命令,用VS做项目 |
| PSP2.1 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|
| Planning 计划 | 30 | 40 |
| · Estimate · 估计这个任务需要多少时间 |
30 | 40 |
| Development 开发 | 240 | 300 |
| · Analysis · 需求分析 (包括学习新技术) |
30 | 60 |
| · Design Spec · 生成设计文档 |
20 | 20 |
| · Design Review · 设计复审 |
15 | 30 |
| · Coding Standard · 代码规范 |
10 | 10 |
| · Design · 具体设计 |
30 | 40 |
| · Coding · 具体编码 |
90 | 120 |
| · Code Review · 代码复审 |
20 | 30 |
| · Test · 测试(自我测试,修改代码,提交修改) |
30 | 50 |
| Reporting 报告 | 50 | 80 |
| · Test Report · 测试报告 |
20 | 30 |
| · Size Measurement · 计算工作量 |
10 | 10 |
| · Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 |
20 | 40 |
| 合计 | 320 | 420 |
代码查重模块设计文档
模块结构设计
1. 代码组织架构
采用面向过程的模块化设计,包含头文件和实现文件:
├── PlagiarismCheck.h // 接口声明
├── readFile.cpp // 文件读取实现
├── calculate.cpp // 查重算法核心
└── main.cpp // 命令行交互逻辑
核心实现细节
🛠️ 核心算法 - LCS动态规划 | O(nm)复杂度
算法实现三步走:
1. 构建DP表
std::vector<std::vector<int>> dp(a.size()+1, std::vector<int>(b.size()+1, 0));
// dp[i][j] 表示原文前i字符与抄袭文前j字符的LCS长度
2. 递推关系
if(a[i-1] == b[j-1]) {
dp[i][j] = dp[i-1][j-1] + 1; // 字符匹配
} else {
dp[i][j] = std::max(dp[i-1][j], dp[i][j-1]); // 不匹配取扩散最大值
}
3.相似度计算
\[\text{相似度} = \frac{2 \times LCS长度}{原文长度 + 抄袭文长度} \
\]
2. 组件关系说明
graph TD
A(main函数) --> B[readFile加载原文]
A --> C[readFile加载抄袭文]
B --> D[calculateSimilarity]
C --> D
D --> E[lcs计算LCS]
E --> D
D --> F[输出百分比结果]
计算模块性能优化方案
性能瓶颈分析
原始性能热点分布
| 函数名称 | CPU占比 | 内存占用(MB) | 调用次数 | 平均耗时(ms) |
|---|---|---|---|---|
| lcs | 92.7% | 210.4 | 1 | 2856 |
| readFile | 5.1% | 18.2 | 2 | 112 |
| calculateSimilarity | 1.3% | 0.8 | 1 | 38 |
具体优化措施
滚动数组优化
// 改进前:
vector<vector<int>> dp(m+1, vector<int>(n+1));
// 改进后:
vector<int> pre_row(n+1), curr_row(n+1);
for(int i=1; i<=m; ++i){
swap(pre_row, curr_row); // 滚动数组核心逻辑
for(int j=1; j<=n; ++j){
if(text1[i-1] == text2[j-1])
curr_row[j] = pre_row[j-1] + 1;
else
curr_row[j] = max(pre_row[j], curr_row[j-1]);
}
}
计算模块异常处理设计说明
本模块共设计3类异常,覆盖文件IO、数据验证等核心场景的异常处理
1. 文件不存在异常 (FileNotFoundException)
设计目标
- 应用场景: 输入文件路径无效或无法访问
- 风险管控: 避免后续处理空指针导致程序崩溃
- 用户提示: 通过友好提示加速故障排除
单元测试样例
TEST(FileTest, InvalidFilePath) {
Calculator calc;
ASSERT_THROW({
calc.processFile("non_existent.txt", "output.txt");
}, FileNotFoundException);
}
2. 空文件异常 (EmptyFileException)
设计目标
- 应用场景: 输入文件内容为空或全部空白符
- 质量保障: 防止解析无效数据浪费计算资源
- 诊断标识: 明确区分文件权限错误与内容错误
单元测试样例
TEST(FileTest, EmptyFileHandling) {
// 预先创建空测试文件 empty_test.txt
Calculator calc;
ASSERT_THROW({
calc.validateContent("empty_test.txt");
}, EmptyFileException);
}
3. 矩阵维度异常 (MatrixDimensionMismatchException)
设计目标
- 应用场景
当LCS算法计算相似度时,矩阵行数与列数不匹配 - 风险拦截层级
算法核心计算前进行维度预检查 - 复用性
可扩展至其他需要矩阵运算的模块
单元测试样例
// 单元测试用例:不同维度的矢量点乘
TEST(CalculatorTest, InvalidVectorDimensions) {
vector<int> vec1 = {1, 2, 3}; // 长度3
vector<int> vec2 = {4, 5}; // 长度2
ASSERT_THROW(
MatrixUtil::calculateDotProduct(vec1, vec2),
MatrixDimensionMismatchException
);
}

浙公网安备 33010602011771号