作业-个人项目编程

news/2025/3/10 17:56:59/文章来源:https://www.cnblogs.com/hjh7201/p/18759692
作业gitHub 作业链接
这个作业属于哪个课程 软件工程
这个作业要求在哪里 作业要求
这个作业的目标 完成一次个人项目

  • 计算模块接口的设计与实现过程

1. 代码组织

计算模块的核心功能是读取文件内容并计算两个文本的相似度。代码组织如下:

模块划分

  1. 文件读取模块

    • 函数:readFile
    • 功能:读取指定文件的内容并返回字符串。
  2. 相似度计算模块

    • 函数:calculateCosineSimilarity
    • 功能:计算两个文本的余弦相似度。
  3. 主程序模块

    • 函数:main
    • 功能:处理命令行参数,调用文件读取和相似度计算模块,并输出结果。

2. 函数设计

2.1 readFile 函数

  • 功能:读取指定文件的内容并返回字符串。
  • 输入:文件路径(const char* filePath)。
  • 输出:文件内容(char*)。
  • 实现
    char* readFile(const char* filePath) {FILE* file = fopen(filePath, "r");if (!file) {fprintf(stderr, "Error: Could not open file %s\n", filePath);return NULL;}fseek(file, 0, SEEK_END);long fileSize = ftell(file);fseek(file, 0, SEEK_SET);char* content = (char*)malloc(fileSize + 1);if (!content) {fclose(file);fprintf(stderr, "Error: Memory allocation failed\n");return NULL;}fread(content, 1, fileSize, file);content[fileSize] = '\0';fclose(file);return content;
    }
    

2.2 calculateCosineSimilarity 函数

  • 功能:计算两个文本的余弦相似度。
  • 输入:两个文本(const char* text1const char* text2)。
  • 输出:相似度(double,范围 0 到 1)。
  • 实现
    double calculateCosineSimilarity(const char* text1, const char* text2) {int vec1[256] = {0};int vec2[256] = {0};// 统计字符频率for (int i = 0; text1[i]; i++) vec1[(int)text1[i]]++;for (int i = 0; text2[i]; i++) vec2[(int)text2[i]]++;// 计算点积和模double dotProduct = 0, magnitude1 = 0, magnitude2 = 0;for (int i = 0; i < 256; i++) {dotProduct += vec1[i] * vec2[i];magnitude1 += vec1[i] * vec1[i];magnitude2 += vec2[i] * vec2[i];}magnitude1 = sqrt(magnitude1);magnitude2 = sqrt(magnitude2);if (magnitude1 == 0 || magnitude2 == 0) return 0.0;return dotProduct / (magnitude1 * magnitude2);
    }
    

2.3 main 函数

  • 功能:处理命令行参数,调用文件读取和相似度计算模块,并输出结果。
  • 输入:命令行参数(int argc, char* argv[])。
  • 输出:将相似度写入输出文件。
  • 实现
    int main(int argc, char* argv[]) {if (argc != 4) {fprintf(stderr, "Usage: %s <original_file> <copy_file> <output_file>\n", argv[0]);return 1;}char* originalText = readFile(argv[1]);char* copyText = readFile(argv[2]);if (!originalText || !copyText) {free(originalText);free(copyText);return 1;}double similarity = calculateCosineSimilarity(originalText, copyText);FILE* outputFile = fopen(argv[3], "w");if (!outputFile) {fprintf(stderr, "Error: Could not open output file %s\n", argv[3]);free(originalText);free(copyText);return 1;}fprintf(outputFile, "%.2f", similarity);fclose(outputFile);free(originalText);free(copyText);return 0;
    }
    

3. 算法关键点

  1. 字符频率统计

    • 使用两个长度为 256 的数组(vec1vec2)统计两个文本中每个字符的频率。
    • 通过遍历文本,将字符的 ASCII 值作为索引,统计频率。
  2. 余弦相似度计算

    • 余弦相似度公式: 相似度=(点积)/(模1*模2)
    • 点积:两个向量的对应元素相乘后求和。
    • 模:向量的长度,计算方法是平方和后开方。
  3. 异常处理

    • 文件不存在或无法读取时,返回 NULL
    • 输出文件无法创建时,输出错误信息并退出。

4. 独到之处

  1. 简单高效
    • 使用字符频率统计和余弦相似度计算,算法简单且高效。
  2. 适用于短文本
    • 算法特别适合短文本查重,计算速度快。
  3. 可扩展性强
    • 可以通过改进字符频率统计方法(如使用哈希表)支持更复杂的文本处理。

计算模块接口的性能改进

  1. 性能改进

    • 初始版本使用简单的字符频率统计,性能较低。
    • 改进思路:优化字符频率统计逻辑,减少不必要的计算。
  2. 性能分析图


单元测试展示

1. 单元测试代码

#include <stdio.h>
#include <assert.h>
#include "plagiarism_checker.h"// 测试读取文件功能
void test_readFile() {const char* filePath = "tests/orig.txt";char* content = readFile(filePath);assert(content != NULL); // 确保文件内容不为空printf("test_readFile passed!\n");
}// 测试计算余弦相似度功能
void test_calculateCosineSimilarity() {const char* text1 = "今天是星期天,天气晴,今天晚上我要去看电影。";const char* text2 = "今天是周天,天气晴朗,我晚上要去看电影。";double similarity = calculateCosineSimilarity(text1, text2);assert(similarity > 0 && similarity < 1); // 确保相似度在合理范围内printf("test_calculateCosineSimilarity passed!\n");
}// 测试文件不存在异常
void test_fileNotFound() {const char* filePath = "tests/nonexistent.txt";char* content = readFile(filePath);assert(content == NULL); // 确保文件不存在时返回 NULLprintf("test_fileNotFound passed!\n");
}// 测试输出文件异常
void test_outputFileError() {const char* outputPath = "invalid/path/ans.txt";FILE* file = fopen(outputPath, "w");assert(file == NULL); // 确保输出文件无法创建时返回 NULLprintf("test_outputFileError passed!\n");
}int main() {test_readFile();test_calculateCosineSimilarity();test_fileNotFound();test_outputFileError();return 0;
}

2. 构造测试数据的思路

  • test_readFile

    • 测试数据:tests/orig.txt 文件。
    • 测试目的:验证 readFile 函数能否正确读取文件内容。
    • 构造思路:使用一个已知的文件路径,确保文件存在且内容不为空。
  • test_calculateCosineSimilarity

    • 测试数据:两段相似的文本。
    • 测试目的:验证 calculateCosineSimilarity 函数能否正确计算相似度。
    • 构造思路:使用两段相似的文本,确保相似度在合理范围内(0 到 1 之间)。
  • test_fileNotFound

    • 测试数据:一个不存在的文件路径。
    • 测试目的:验证 readFile 函数在文件不存在时能否正确处理异常。
    • 构造思路:使用一个不存在的文件路径,确保函数返回 NULL
  • test_outputFileError

    • 测试数据:一个无效的输出文件路径。
    • 测试目的:验证程序在输出文件无法创建时能否正确处理异常。
    • 构造思路:使用一个无效的路径,确保 fopen 返回 NULL

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

  1. 异常设计

    • 文件不存在异常:如果输入文件路径错误,程序会输出错误信息并退出。
    • 文件读取异常:如果文件无法读取,程序会输出错误信息并退出。
    • 输出文件异常:如果输出文件无法创建,程序会输出错误信息并退出。
  2. 单元测试样例

    • 示例 1:测试文件不存在异常。
      void test_fileNotFound() {const char* filePath = "tests/nonexistent.txt";char* content = readFile(filePath);assert(content == NULL);printf("test_fileNotFound passed!\n");
      }
      
    • 示例 2:测试输出文件异常。
      void test_outputFileError() {const char* outputPath = "invalid/path/ans.txt";FILE* file = fopen(outputPath, "w");assert(file == NULL);printf("test_outputFileError passed!\n");
      }
      

  • PSP表格

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

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

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

相关文章

mybatis-plus02--Lesson2

CRUD和myBatis-plus插件 1.Insert方法和雪花算法 当一个数据表中的id为主键时,且插入的数据的时候不插入主键id,那么会发生什么呢?接下来就进行一次简单测试,还是那个User表,插入其它属性,不插入主键id。 测试方法:@Testpublic void testInsert(){User user = new User(…

免费好用的云服务器提供商

最近倒腾云服务器,想在阿里云上购买,结果发现价格太高,是在买不起。我只好在百度上翻呀翻,终于找到一个免费的,实名一下就能用。链接我贴这儿了,要用请自取:免费好用的云服务器提供商

2020-PTA总决赛-L3-1 那就别担心了(记忆化搜索)

dfs,记忆化搜索思路:读懂题到28分花了十分钟左右,做的时候就感觉可能要超时,因为结点稍微有点多 但是还是继续硬着头皮写下去了,果不其然,最后一个测试点超时,那么就要开dp数组了 题目大意就是找到A到B有几条路径,且是否走哪条路都能通向B28分Code: #include<bits/st…

集合论3 公理化—从罗素悖论到集合的公理化定义

集合论3 公理化—从罗素悖论到集合的公理化定义 罗素悖论 若把所有集合分为两类:第一类中的集合以其自身为元素,第二类中的集合不以自身为元素。 设第一类集合所组成的集合为\(P\),第二类所组成的集合为\(Q\)。于是有: \(P=\{A |A \in A\}\), \(Q=\{A |A \notin A\}\)。 试…

集合论2序数——从自然数系统到无穷集合的排序

集合论2序数——从自然数系统到无穷集合的排序 我们上一节,回答了下面几个关键问题 1 一个无穷集合有多少个元素?——自然数集:\(\aleph_0\),实数集:\(C=2^{\aleph_0}\) 2 不同的无穷集合里的元素“数量”是否有差异?——可数集(自然数集),不可数集(实数集—连续统)…

软件工程-作业2:第一次个人编程作业:论文查重

项目 内容这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/SoftwareEngineeringClassof2023这个作业在哪里 https://edu.cnblogs.com/campus/gdgy/SoftwareEngineeringClassof2023/homework/13324这个作业的目标 学会如何个人系统化地完成软件开发,学会使用性能测试…

换到Edge?我有几点不满意。

前言 向来我都是用百分浏览器这个套壳Chrome,然而在迁移的时候由于网络的原因,存在各种不方便,于是我试着去用Edge,虽然之前也在用,但从来没作为主力使用过。 不足之处 收藏功能一塌糊涂 当我右键某个书签文件夹时,选择添加该网页,他居然要我重新选书签所在的文件夹。更…

【端口转发】 lcx工具

lcx是一个居于socket套接字实现的端口转发工具,有windows和linux两个版本,windows叫lcx.exe,linux叫portmap 一个正常的socket隧道必须具备两端:服务器端和客户端 windows下: 1、转发端口: lcx.exe -slave 公网IP 端口 内网IP 端口2、监听端口: lcx.exe -listen 转发端口…

Manus验证码生成器

Manus验证码生成器 Manus 是Monica团队推出的全球首款通用型AI助手,能将想法转化为行动:不止于思考,更注重成果。 一、关注公众号二、从底部菜单中进入三、使用Manus验证码生成器本文来自博客园,作者:方倍工作室,转载请注明原文链接:https://www.cnblogs.com/txw1958/p/…

洛谷 P1111 修复公路(并查集)

并查集这题如果想到是并查集就很简单了,按t来排序一下就好了AcCode: #include<bits/stdc++.h> using namespace std; struct way{int v1, v2, t; }; bool Cmp(const way &a, const way &b){return a.t < b.t; }vector<way> w; int unionList[1010];int…

实验1 C语言输入输出和简单程序应用编程

任务1: 源代码:1 #include <stdio.h>2 #include <stdlib.h>3 4 int main()5 {6 printf(" o \n");7 printf("<H>\n");8 printf("I I\n");9 printf(" o \n"); 10 printf("<H>\n&quo…

某考核wp

就这样抱着胸中的苦痛,前往没有你的未来My Blog robots.txt进level1.php <?php error_reporting(0); highlight_file(__FILE__); $text = $_GET["text"]; $file = $_GET["file"]; if(isset($text)&&(!preg_match("/php/",$text))…