第二次软工作业——个人项目 - LXJ

news/2025/9/22 18:21:55/文章来源:https://www.cnblogs.com/Apple-xu/p/19105787

github仓库:https://github.com/ApplePI-xu/3123004185

这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience
这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience/homework/13469
这个作业的目标 了解项目开发的基本流程,熟悉git使用方式

一. PSP

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 15 15
Estimate 估计这个任务需要多少时间 10 10
Development 开发 180 240
Analysis 需求分析(包括学习新技术) 60 60
Design Spec 生成设计文档 25 20
Design Review 设计复审 15 10
Coding Standard 代码规范(为目前的开发制定合适的规范) 20 20
Design 具体设计 40 50
Coding 具体编码 120 150
Code Review 代码复审 20 15
Test 测试(自我测试,修改代码,提交修改) 30 40
Reporting 报告 60 90
Test Report 测试报告 10 10
Size Measurement 计算工作量 5 5
Postmortem & Process Improvement Plan 事后总结,并提出过程改进计划 10 5

二. 模块接口设计与实现过程

项目结构

paper-similarity-checker/
├── cmd/
│ └── main.go # 程序入口,处理命令行参数
├── internal/
│ ├── similarity/
│ │ ├── checker.go # 查重核心逻辑
│ │ ├── tokenizer.go # 文本分词处理
│ │ └── algorithms.go # 相似度算法实现
│ └── utils/
│ ├── file_handler.go # 文件读写处理
│ └── formatter.go # 结果格式化
├── test/
│ ├── test_data/
│ │ ├── orig.txt # 测试用例:原文
│ │ ├── orig_0.8_add.txt # 测试用例:添加版
│ │ ├── orig_0.8_del.txt # 测试用例:删减版
│ │ ├── orig_0.8_dis_1.txt # 测试用例:微调版
│ │ ├── orig_0.8_dis_10.txt # 测试用例:大幅调整
│ │ └── orig_0.8_dis_15.txt # 测试用例:极大调整
│ ├── integration_test.go # 主流程集成测试
│ └── orig_file_test.go # 文件批量相似度测试
├── go.mod # Go模块文件
├── go.sum # 依赖锁定文件
└── README.md # 项目说明文档

模块设计表

模块名称 文件路径 主要功能 核心接口/函数 依赖关系
主程序模块 main() 程序入口、参数解析、流程控制 main() similarity,utils
查重检查器 internal/similarity/checker.go 相似度检测协调器 NewChecker(), CalculateSimilarity() algorithms, tokenizer
算法实现模块 internal/similarity/algorithms.go 核心算法实现 EditDistance(), CalcCharSimilarity(), CalcSegSimilarity()
文本分词器 internal/similarity/tokenizer.go 文本预处理和分段 SplitTextIntoSegments(), SplitSegIntoSentences()
文件处理器 internal/utils/file_handler.go 文件读写操作 ReadFile(), WriteFile()
结果格式化器 internal/utils/formatter.go 结果格式化输出 FmtSimilarityAsPct()

模块实现说明

1. 主程序模块 (main.go)

  • 职责: 程序入口点,处理命令行参数,协调各模块
  • 输入: 命令行参数 (原文件路径, 抄袭文件路径, 输出文件路径)
  • 输出: 相似度结果文件 + 控制台信息
  • 异常处理: 参数检查、文件操作异常

1. 查重检查器模块 (checker.go)

type Checker struct {tokenizer  *Tokenizeralgorithms *Algorithms
}func NewChecker() *Checker
func (c *Checker) CalculateSimilarity(original, plagiarized string) float64
  • 职责: 相似度检测的核心协调器
  • 算法流程: 文本分段 → 段落匹配 → 相似度计算 → 加权平均

算法实现模块 (algorithms.go)

type Algorithms struct{}func NewAlgorithms() *Algorithms
func (a *Algorithms) EditDistance(str1, str2 string) int
func (a *Algorithms) CalcCharSimilarity(str1, str2 string) float64
func (a *Algorithms) CalcSegSimilarity(segs1, segs2 []string) float64
  • 职责: 核心查重算法实现
  • 核心算法: Levenshtein编辑距离算法
  • 优化特性: 动态规划实现,支持Unicode字符

1.文本分词器模块 (tokenizer.go)

type Tokenizer struct{}func NewTokenizer() *Tokenizer
func (t *Tokenizer) SplitTextIntoSegments(text string) []string
func (t *Tokenizer) SplitSegIntoSentences(segment string) []string
  • 职责: 文本预处理和智能分段
  • 分段策略:
    • 按双换行符分割段落
    • 长段落(>200字符)按句子分割
    • 支持中英文混合文本

1. 结果格式化器模块 (formatter.go)

type Formatter struct{}func NewFormatter() *Formatter
func (f *Formatter) FmtSimilarityAsPct(similarity float64) string
  • 职责: 格式化输出
  • 输出格式: 百分比形式,保留2位小数

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

1. 性能分析现状

使用pprof工具进行性能分析

CPU性能分析

Snipaste_2025-09-22_16-04-44

可看出耗时最长的操作是执行编辑距离查重算法函数——EditDistance(22.45%)

主要CPU消耗分布:

  • EditDistance函数: 22.45% - 最大CPU消耗
  • runtime.stdcall2: 15.40% - 系统调用开销

内存性能分析

Snipaste_2025-09-22_16-07-44

主要内存消耗分布

  1. EditDistance算法瓶颈
    • CPU占用22.45%,是最大的性能热点
    • 涉及大量动态规划计算
    • 字符串到rune切片的转换开销
  2. 系统调用开销
    • stdcall1/stdcall2占用21.62%的CPU
    • 可能涉及文件I/O操作

2.性能优化思路

CPU优化思路:并发文件读取

现状问题: 当前是串行读取两个文件,I/O操作阻塞CPU

优化方案: 使用goroutine并发读取文件

优化效果: 文件I/O时间减少约50%,特别是处理大文件时效果明显

内存优化思路:流式处理大文件

现状问题: 当前将整个文件内容加载到内存中,大文件会占用大量内存

优化方案: 对于大文件使用流式分块处理

优化效果: 内存使用从"文件大小"降至固定的4KB缓冲区

总结

  • CPU优化:并发I/O减少等待时间,提升CPU利用率
  • 内存优化:流式处理避免大文件全量加载,大幅降低内存峰值

四. 计算模块部分单元测试展示

1.项目结果测试

自定义文本

测试组结构

	type testCase struct {name     stringorig     stringplag     stringexpectLo float64expectHi float64}

测试逻辑

	checker := similarity.NewChecker()for _, tc := range tests {t.Run(tc.name, func(t *testing.T) {sim := checker.CalculateSimilarity(tc.orig, tc.plag)if sim < tc.expectLo || sim > tc.expectHi {t.Errorf("%s: 相似度 %.4f 不在期望范围 [%.2f, %.2f]", tc.name, sim, tc.expectLo, tc.expectHi)}})}
}

测试结果

Snipaste_2025-09-22_17-20-39

要求文本

测试组结构及测试数据(包含结果的预期范围)

	cases := []struct {file     stringexpectLo float64expectHi float64}{{"orig_0.8_add.txt", 0.6, 0.9},{"orig_0.8_del.txt", 0.6, 0.9},{"orig_0.8_dis_1.txt", 0.6, 0.9},{"orig_0.8_dis_10.txt", 0.6, 0.85},{"orig_0.8_dis_15.txt", 0.5, 0.8},}

测试逻辑

	for _, c := range cases {c := c // 避免闭包变量问题t.Run(c.file, func(t *testing.T) {plagData, err := os.ReadFile(basePath + c.file)if err != nil {t.Errorf("无法读取抄袭文件 %s: %v", c.file, err)return}sim := checker.CalculateSimilarity(string(origData), string(plagData))if sim < c.expectLo || sim > c.expectHi {t.Errorf("%s: 相似度 %.4f 不在期望范围 [%.2f, %.2f]", c.file, sim, c.expectLo, c.expectHi)}})}

测试结果

Snipaste_2025-09-22_17-25-23

2.部分函数单元测试

核心查重算法algorithms.go函数的单元测试

// TestEditDistance 测试编辑距离计算
func TestEditDistance(t *testing.T) {algorithms := NewAlgorithms()tests := map[string]struct {input1 stringinput2 stringoutput int}{// 经典测试用例"kitten_sitting":      {"kitten", "sitting", 3},...// 边界情况"both_empty":   {"", "", 0},...}for name, tt := range tests {t.Run(name, func(t *testing.T) {result := algorithms.EditDistance(tt.input1, tt.input2)if result != tt.output {t.Errorf("expected %d, got %d", tt.output, result)}})}
}// TestCalcCharSimilarity 测试字符相似度计算
func TestCalcCharSimilarity(t *testing.T) {algorithms := NewAlgorithms()tests := map[string]struct {input1 stringinput2 stringoutput float64}{// 基于编辑距离的相似度测试"kitten_sitting":      {"kitten", "sitting", 0.571429},...// 边界情况"both_empty":       {"", "", 1.0},...}for name, tt := range tests {t.Run(name, func(t *testing.T) {result := algorithms.CalcCharSimilarity(tt.input1, tt.input2)if abs(result-tt.output) > 0.000001 {t.Errorf("expected %f, got %f", tt.output, result)}})}
}// TestCalcSegSimilarity 测试分段相似度计算
func TestCalcSegSimilarity(t *testing.T) {algorithms := NewAlgorithms()tests := map[string]struct {segs1    []stringsegs2    []stringexpected float64}{// 功能测试"chinese_text":   {[]string{"你好", "今天是晴天"}, []string{"你啊哈好", "今天天气晴朗"}, 0.5},...// 边界情况"both_empty":        {[]string{}, []string{}, 1.0},...}for name, tt := range tests {t.Run(name, func(t *testing.T) {result := algorithms.CalcSegSimilarity(tt.segs1, tt.segs2)if abs(result-tt.expected) > 0.000001 {t.Errorf("%s: expected %f, got %f", name, tt.expected, result)}})}
}

测试结果

Snipaste_2025-09-22_17-43-45

如图所示,该单元测试覆盖率为100%

四. 计算模块部分异常处理说明

1. 1. 主程序异常处理(cmd/main.go)

参数数量异常

if len(os.Args) != 4 {fmt.Fprintf(os.Stderr, "参数错误: %d\n", len(os.Args)-1)fmt.Fprintf(os.Stderr, "使用方法: %s <原文文件路径> <抄袭版文件路径> <输出文件路径>\n", os.Args[0])os.Exit(1)}

测试样例:

# 参数数量错误
[]                                    # 无参数
["file1.txt"]                        # 参数不足
["f1.txt", "f2.txt"]                 # 参数不足  
["f1.txt", "f2.txt", "f3.txt", "f4.txt"] # 参数过多

文件操作异常处理 (internal/utils/file_handler.go)

读取文件异常

    // 1. 文件路径为空if filePath == "" {return "", errors.New("文件路径不能为空")}// 2. 文件不存在if _, err := os.Stat(filePath); os.IsNotExist(err) {return "", fmt.Errorf("文件不存在: %s", filePath)}// 3. 文件读取权限content, err := os.ReadFile(filePath)if err != nil {return "", fmt.Errorf("读取文件失败: %v", err)}

写入文件异常

func (fh *FileHandler) WriteFile(filePath, content string) error {// 1. 文件路径为空if filePath == "" {return errors.New("输出文件路径不能为空")}// 2. 创建目录dir := filepath.Dir(filePath)if err := os.MkdirAll(dir, 0755); err != nil {return fmt.Errorf("创建目录失败: %v", err)}// 3. 写入文件if err := os.WriteFile(filePath, []byte(content), 0644); err != nil {return fmt.Errorf("写入文件失败: %v", err)}return nil
}

测试样例:

// ReadFile 异常参数
""                           // 空路径
"nonexistent_file.txt"      // 不存在的文件
"/root/no_permission.txt"   // 无权限文件
"../../../etc/passwd"       // 路径遍历
"con"                       // Windows保留名
"\x00invalid"               // 包含NULL字符的路径// WriteFile 异常参数
("", "content")                    // 空输出路径
("/dev/null/file.txt", "content") // 无效目录
("readonly_dir/file.txt", "")     // 只读目录

3. 相似度计算异常处理 (internal/similarity/checker.go)

package similarityimport "errors"type Checker struct {algorithms *Algorithmstokenizer  *Tokenizer
}func NewChecker() *Checker {return &Checker{algorithms: NewAlgorithms(),tokenizer:  NewTokenizer(),}
}func (c *Checker) CalculateSimilarity(text1, text2 string) float64 {// 1. 输入验证 - 两个文本都为空if text1 == "" && text2 == "" {return 1.0}// 2. 输入验证 - 其中一个为空if text1 == "" || text2 == "" {return 0.0}// 3. 分词异常处理segments1 := c.tokenizer.Tokenize(text1)segments2 := c.tokenizer.Tokenize(text2)// 4. 计算相似度return c.algorithms.CalcSegSimilarity(segments1, segments2)
}

测试样例:

// CalculateSimilarity 异常参数
("", "")                              // 双空文本
("", "非空文本")                      // 原文为空
("非空文本", "")                      // 抄袭文本为空
(strings.Repeat("a", 100000), strings.Repeat("b", 100000)) // 超长文本
("   \n\t  ", " \t\n   ")            // 只有空白字符
("Hello 🌍 \u200B", "Hello 🌍 \u200B") // Unicode特殊字符
("!@#$%^&*()", "!@#$%^&*()")         // 特殊符号

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/909956.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WinForm引入项目资源文件

以Buttom按钮为例去引入 ,在Debug文件目录下 , 新建一个images文件夹 ,然后把要使用的资源(图片)拖进去 ​将资源加载到项目中去 ,点击 Properties下面的Resoures.resx , 然后把图片直接拖进去 效果如下: ​这个…

猪八戒做网站排名网页设计制作教程

消息队列在使用过程中会出现很多问题 首先就是消息的可靠性&#xff0c;也就是消息从发送到消费者接收&#xff0c;消息在这中间过程中可能会丢失 生产者到交换机的过程、交换机到队列的过程、消息队列中、消费者接收消息的过程中&#xff0c;这些过程中消息都可能会丢失。 …

境外社交网站上做推广手机排名

一、准备两台主机&#xff0c;区分主从 二、完全区域传送 1、主DNS服务器配置 #安装相关的包 [rootoula1 ~]# yum install bind -y#关闭防火墙 [rootoula1 ~]# systemctl stop firewalld [rootoula1 ~]# setenforce 0#修改配置主文件 [rootoula1 ~]# vim /etc/named.conf opt…

广州百度网站推广设计网站app

WFilter NGF的“Web认证”模块&#xff0c;提供了一系列的上网认证解决方案。包括如下认证方式&#xff1a;本地用户名密码认证AD域用户名密码认证企业邮箱用户名密码认证Radius用户名密码认证微信WiFi认证Facebook Wifi认证除此&#xff0c;WFilter NGF还有一个“其他”的选项…

政务网站建设 发言山东省中国建设银行网站

精华置顶 墙裂推荐&#xff01;小白如何1个月系统学习CV核心知识&#xff1a;链接 点击CV计算机视觉&#xff0c;关注更多CV干货 论文已打包&#xff0c;点击进入—>下载界面 点击加入—>CV计算机视觉交流群 1.【目标检测】Re-Scoring Using Image-Language Similarit…

建设部网站官网造价系统广州网站设计哪里好

概念 发生在使用模板引擎解析用户提供的输入时。模板注入漏洞可能导致攻击者能够执行恶意代码或访问未授权的数据。 模板引擎可以让&#xff08;网站&#xff09;程序实现界面与数据分离&#xff0c;业务代码与逻辑代码分离。即也拓宽了攻击面&#xff0c;注入到模板中的代码可…

网站服务器维护内容php网站里放asp

在云计算和数据中心领域&#xff0c;Linux虚拟化作为基础设施的核心组件&#xff0c;为资源的高效利用和应用程序的灵活部署提供了坚实的基础。然而&#xff0c;尽管其优势显著&#xff0c;虚拟化环境下的性能损失问题仍然是一个不可忽视的挑战。本文将深入探讨Linux虚拟化中性…

中文网站域名外国网站做vr

Linux、Docker、Brew、Nginx常用命令 Linuxvi编辑器文件操作文件夹操作磁盘操作 DockerBrewNginx参考 Linux vi编辑器 Vi有三种模式。命令模式、输入模式、尾行模式&#xff0c;简单的关系如下&#xff1a; i -- 切换到输入模式&#xff0c;在光标当前位置开始输入文本。&a…

淘宝网站开发费用关于建设工程招标的网站

昨天&#xff08;11月17日&#xff09;升级到Windows 10 Threshold 2版本。我的使用的设备是Surface Pro 3&#xff0c;4G内存&#xff0c;128G硬盘。 Threshold 2是作为一个Windows系统更新推送的。如果没有收到系统更新提示&#xff0c;在系统设置里面手动检查一下更新就可以…

网站制作珠海公司asp.net 发布网站 ftp

1、类型转换构造 |自定义转换 利用一个已定义的对象,来定义另一个不同类型的对象 实现从源类型到目标类型的隐式类型转换的目的 总结下已知构造&#xff0c;包括类型转换构造 如下&#xff0c;如果Person给Human赋值时&#xff0c;Person有私有变量&#xff0c;则需要在Pers…

详细介绍:uniapp | u-waterfall实现瀑布流商品列表(支持筛选查询)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

注册公司网站怎么做太原网络公司网站

文章目录 持久化配置慢查询命令及安全配置内存配置 持久化配置 慢查询 命令及安全配置 漏洞&#xff1a;Redis未授权访问配合SSH key文件利用分析-腾讯云开发者社区-腾讯云 (tencent.com) 漏洞出现的核心的原因有以下几点 Redis未设置密码利用了Redis的config set命令动态修…

企业网站内容如何搭建wordpress主题代码放在哪里

书接上回 上回讲到创建一个示例工程 今天讲如何实现LED的点亮 点亮一个led 所需代码 参考来源网络 延时函数参考&#xff1a; Delay.c #include "stm32f10x.h"/*** brief 微秒级延时* param xus 延时时长&#xff0c;范围&#xff1a;0~233015* retval 无*/ vo…

政务系统网站知乎 wordpress 博客

一、题目描述 给你二叉树的根节点 root &#xff0c;返回其节点值 自底向上的层序遍历 。 &#xff08;即按从叶子节点所在层到根节点所在的层&#xff0c;逐层从左向右遍历&#xff09; 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[…

优化网站步骤常州做网站哪里好

参考&#xff1a;59_Dockerfile保留字简介_哔哩哔哩_bilibili FROM 作用&#xff1a;指定基础镜像&#xff0c;即在这个基础镜像上构建新镜像&#xff0c;如下所示&#xff0c;表示在ubuntu20.04镜像的基础上构建新镜像 FROM ubuntu:20.04 MAINTAINER 作用&#xff1a;镜像…

国内目前比较好的crm系统wordpress优化速度

为什么在大型项目中data需要使用return返回数据呢&#xff1f;答&#xff1a;不使用return包裹的数据会在项目的全局可见&#xff0c;会造成变量污染&#xff1b;使用return包裹后数据中变量只在当前组件中生效&#xff0c;不会影响其他组件。 1、在简单的vue实例中看到的Vue实…

网站优化关键词怎么做张家港网站开发培训

LDA&#xff1a;LDA最大化类间距离&#xff0c;最小化类内距离&#xff0c;使得投影后的不同类别的样本分的更开&#xff0c;属于监督学习。 PCA&#xff1a;PCA最小重构误差&#xff0c;使得投影后的值和原来的值尽量接近&#xff0c;属于非监督学习。 SVM&#xff1a;最大间…

怎样弄一个自己的网站建设监理协会网站

注&#xff1a;题目来源均出自牛客网。 一、选择题 Map&#xff08;集合&#xff09;属于Go的内置类型&#xff0c;不需要引入其它库即可使用。 Go-Map_菜鸟教程 在函数声明中&#xff0c;返回的参数要么都有变量名&#xff0c;要么都没有。 C选项函数声明语法有错误&#xff0…