第一次个人编程作业

这个作业属于哪个课程:https://edu.cnblogs.com/campus/gdgy/Class78-Grade2024-CS

这个作业要求在哪里:https://edu.cnblogs.com/campus/gdgy/Class78-Grade2024-CS/homework/15702
这个作业的目标:通过程序实现论文的查重功能

本次作业的GIthub网址:https://github.com/Duan-12345/Duan-12345/commit/1d00f163c1b478826202ad22cdf0bf42b6a53ba1
我的PSP表格:
image
计算模块接口的设计和实现过程:

本项目使用 C 语言实现文本查重,按照功能拆分为4 个核心模块,采用函数式接口组织代码,没有类的概念:

  1. 文本预处理模块
    接口:char* preprocess(const char* text)
    功能:过滤文本中的标点符号,统一文本格式,返回清洗后的字符串。
    2.2-gram 哈希表模块
    接口:HashTable* build_2gram_map(const char* text)void hash_insert(HashTable* table, const char* gram)int hash_get(HashTable* table, const char* gram)void hash_destroy(HashTable* table)
    功能:把清洗后的文本切分为连续 2 字符的 2-gram 特征,统计每个 2-gram 的出现次数;支持查询词频和释放内存。
  2. 余弦相似度计算模块
    接口:float calc_cosine_similarity(HashTable* a, HashTable* b)
    功能:接收两个哈希表,用余弦公式 (\cos\theta=\frac{\sum a_i b_i}{\sqrt{\sum a_i^2}\sqrt{\sum b_i^2}}) 计算文本相似度。
  3. 文件读写模块
    接口:int read_file(const char* path, char** out_text)int write_result(const char* path, float sim)
    功能:读取待比较文本文件,输出相似度结果到文件。

算法关键:用 2-gram 作为文本特征,能够捕捉局部语义;用哈希表存储特征词频,大幅降低重复统计的开销。
独到之处:预处理逻辑会过滤标点,保证相同内容、不同标点的文本相似度接近 1;哈希表配套内存释放函数,避免内存泄漏。

  1. 计算模块接口部分的性能改进

改进前

使用 VS 性能探查器分析,hash_get是消耗最大的函数。原因:哈希表桶数量设置偏小(1024),哈希碰撞多,查找时需要遍历长链表;预处理模块用大量if判断标点,分支开销大。

改进思路

  1. 将哈希表桶容量从 1024 调整为 8192,减少哈希碰撞,缩短链表长度,降低hash_get的遍历耗时。
  2. 标点判断改用查表法(数组标记是否为标点),替换多层if分支,减少 CPU 分支预测开销。

性能分析图说明

VS 性能探查器(分析→性能探查器)生成的 CPU 使用率报告:

改进前:热路径指向hash_get,占用 CPU 约 42%。
改进后:hash_getCPU 占比下降到 18%,整体程序运行速度提升。

VS 性能探查器截图:image
耗能最大的函数:image
记录耗时:性能分析定位瓶颈耗时约 30 分钟,代码修改与复测耗时约 50 分钟。

  1. 计算模块部分单元测试展示
    image
    image
    image
    image
    image
    测试覆盖率:image

6计算模块部分异常处理声明

读取不存在的文件: 防止程序崩溃,返回错误码,提示用户 调用read_file("none.txt", &buf),预期返回值-1,不触发断言崩溃
输入空文本:防止余弦相似度计算时分母为 0 preprocess(""),两个空文本计算相似度,结果为 0,无除零异常
malloc 内存分配失败 :避免空指针访问,程序安全退出 |模拟内存不足场景,build_2gram_map返回NULL,上层代码判断后不继续执行

posted @ 2026-09-15 00:02  段旷卓  阅读(16)  评论(0)    收藏  举报