第一次个人编程作业

作业所属课程

软件工程2024

作业要求

个人项目

作业目标

设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率。

我的 Github 链接:https://github.com/SmallGoldMedal/3122004499/tree/main

一、需求分析:

需求:
1.对输入的原文文件和抄袭版文件进行重复率分析计算;
2.使用命令行将重复率输出到答案文件内,其中数字精确到小数点后两位。

分析:
对于算法,可将源文件的句子和抄袭版文件的句子逐一比对,以计算重复率。具体而言:
1.在句句比较时,设定:句子内部重复率 = 重复字数与抄袭版文件被检测的句子总字数之比,当句子内部重复率 >= 50% 时,则认为句子涉嫌抄袭;
2.在文章比较时,设定:文章重复率 = 涉嫌抄袭句子数与抄袭版文件总句子数之比,计算结果即为重复率。

二、PSP2表格

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

计算模块接口的设计与实现:

分为三个类:Main,readFile,putFile,其中:

  1. Main 类仅含main函数,引用 readFile() 方法和 putFile() 负责计算重复率;
  2. ReadFile类有 readFile() 方法,负责读入源文件和抄袭版文件;
  3. PutFile 类有 putFile() 方法,负责输出答案文件。

关系图:

文本的切割
public String[] getSentences() {
    try {
        String content = new String(Files.readAllBytes(Paths.get(fileName)));
        //以“。”或换行符为标志对文章进行切割
        return content.split("[。\\n]");
    } catch (IOException e) {
        //出错处理
        System.err.println("读取文件错误: " + fileName);
        e.printStackTrace();
        return new String[0];
    }
}
数据的输出
public static void putContent(String fileName, String content) {
    try {
        Files.write(Paths.get(fileName), content.getBytes());
    } catch (IOException e) {
        //出错处理
        System.err.println("写入文件出错: " + fileName);
        e.printStackTrace();
    }
 
数据处理
int sCount = 0;
for (String pSentence : Sentences2) {
    for (String oSentence : Sentences1) {
        int sameWords = 0;
        String[] pWords = pSentence.split("\\s+");
        String[] oWords = oSentence.split("\\s+");

        for (String pWord : pWords) {
            for (String oWord : oWords) {
                if (pWord.equals(oWord)) {                     
                    sameWords++;
                    break;
                }
            }
        }

        double similarity = (double) sameWords / pWords.length;
        if (similarity >= 0.5) {
            sCount++;
            break;
        }
    }
}

计算模块接口部分的性能:

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

测试输入不同文件下的重复率:

测试代码
public class Test {
    public static void main(String[] args) {
        String test1= "src/main/resources/orig.txt";
        String test2= "src/main/resources/orig_0.8_add.txt";
        String test3= "src/main/resources/orig_0.8_del.txt";
        String test4= "src/main/resources/orig_0.8_dis_1.txt";
        String test5= "src/main/resources/orig_0.8_dis_10.txt";
        String test6= "src/main/resources/orig_0.8_dis_15.txt";
        String test7= "src/main/resources/test_1.txt";
        String ans1="src/main/resources/ans.txt";

        System.out.println("Test1:");
        test(test1,test2,ans1);
        System.out.println("Test2:");
        test(test1,test3,ans1);
        System.out.println("Test3:");
        test(test1,test4,ans1);
        System.out.println("Test4:");
        test(test1,test5,ans1);
        System.out.println("Test5:");
        test(test1,test6,ans1);
        System.out.println("Test6:");
        test(test1,test7,ans1);
    }

    public static void test(String path1, String path2, String path3) {
        //传入ReadFile以分解文本
        ReadFile File1 = new ReadFile(path1);
        ReadFile File2 = new ReadFile(path2);
        String[] Sentences1 = File1.getSentences();
        String[] Sentences2 = File2.getSentences();

        //空文本报错
        if (Sentences1.length == 0 || Sentences2.length == 0) {
            System.out.println("文档有误或路径有误。");
            return;
        }

        //进行统计
        int sCount = 0;
        for (String pSentence : Sentences2) {
            for (String oSentence : Sentences1) {
                int sameWords = 0;
                String[] pWords = pSentence.split("\\s+");
                String[] oWords = oSentence.split("\\s+");

                for (String pWord : pWords) {
                    for (String oWord : oWords) {
                        if (pWord.equals(oWord)) {
                            sameWords++;
                            break;
                        }
                    }
                }

                double similarity = (double) sameWords / pWords.length;
                if (similarity >= 0.5) {
                    sCount++;
                    break;
                }
            }
        }

        double pRate = (double) sCount / Sentences2.length * 100;
        String result = String.format("%.2f%%", pRate);

        //输出重复率
        PutFile.putContent(path3, result);
        System.out.println(result);
    }
}

结果:

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

1.空文本报错
if (Sentences1.length == 0 || Sentences2.length == 0) {
    System.out.println("文档有误或路径有误。");         
    return;
}
2.输入出错
System.err.println("读取文件错误: " + fileName);
e.printStackTrace();
return new String[0];
3.输出出错
System.err.println("写入文件出错: " + fileName);
e.printStackTrace();
posted @ 2024-03-14 01:42  SmallGoldMedal  阅读(20)  评论(0编辑  收藏  举报