论文查重
github链接:https://github.com/fanshaojun/Work/blob/main/202121331108/main.cpp
1. 作业说明
| 这个作业属于哪个课程 | 工程概论 |
|---|---|
| 这个作业要求在哪里 | 第一次个人编程作业 |
| 这个作业的目标 | 学习项目的设计 |
2. 需求分析
题目:论文查重
描述如下:
设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率。
原文示例:今天是星期天,天气晴,今天晚上我要去看电影。
抄袭版示例:今天是周天,天气晴朗,我晚上要去看电影。
要求输入输出采用文件输入输出,规范如下:
从命令行参数给出:论文原文的文件的绝对路径。
从命令行参数给出:抄袭版论文的文件的绝对路径。
从命令行参数给出:输出的答案文件的绝对路径。
我们提供一份样例,课堂上下发,上传到班级群,使用方法是:orig.txt是原文,其他orig_add.txt等均为抄袭版论文。
注意:答案文件中输出的答案为浮点型,精确到小数点后两位
3. 框架流程

4. 主要函数
将原文件中的内容进行存储
infile.open( file.data() ); //将文件流对象与文件连接起来
assert( infile.is_open() ); //若失败,则输出错误消息,并终止程序运行
while ( !infile.eof() )
{
infile>>nowcur;
if((( nowcur >='a' )&&( nowcur <='z' ))||(( nowcur >='A' )&&( nowcur <='Z' )))
{
tempStatement += nowcur;
}else if(( nowcur =='.' )||( nowcur =='?' )||( nowcur =='!' ))
{
transform(tempStatement.begin(), tempStatement.end(), tempStatement.begin(), ::tolower);
temp.nums = num1+1;
temp.statement = tempStatement;
libStatement[libnums] = temp; //按每句子存储org的内容到libStatement[]中
num1 = 0;
tempStatement = "";
libnums++; //org文件的句子的个数
}else //匹配到空格
{
if( tempStatement=="" )
{
continue;
}
else if(tempStatement[tempStatement.size()==1?1:tempStatement.size()-1] != ' ') //匹配到空格,当前句末不为空格,添加空格
{
tempStatement += " ";
num1 += 1; //单词个数加1
}
}
}
infile.close(); //关闭文件输入流
读取test文件中的内容进行比对查重
infile.open( file.data() ); //将文件流对象与文件连接起来
assert( infile.is_open() ); //若失败,则输出错误消息,并终止程序运行
while ( !infile.eof() )
{
infile>>nowcur;
if((( nowcur >='a' )&&( nowcur <='z' ))||(( nowcur >='A' )&&( nowcur <='Z' )))
{
tempStatement += nowcur;
}else if(( nowcur =='.' )||( nowcur =='?' )||( nowcur =='!' )) //完成一个句子的读取,进行动态规划匹配查重
{
transform(tempStatement.begin(), tempStatement.end(), tempStatement.begin(), ::tolower);
temp.nums = num1+1; // 把当前读取到的text句子的单词个数存下
temp.statement = tempStatement; // 把当前读取到的text句子存下
num1 = 0;
tempStatement = "";
for(int i=0;i<libnums-1;i++ ) //分别与org中的每一句进行对比
{
string t;
int n = 0;
int k,j;
for(istringstream is(temp.statement); is>>t;) { //存储把text的句子分割出来的单词
str1[n++] = t;
}
n = 0;
for(istringstream is1(libStatement[i].statement); is1>>t;) { //存储把org的句子分割出来的单词
str2[n++] = t;
}
for( k=0;k<temp.nums;k++) //text当前句子的个数
{
for( j=0;j<libStatement[i].nums;j++) //与org文件的句子的单词分别进行对比
{
if(str1[k]==str2[j])
words[k][j] = 1;
else
words[k][j] = 0;
}
}
for(k=0; k<temp.nums; k++)
{
grade[k][0] = max(grade[k-1][0]-0.5, words[k][0]-0.5*(k-1) );
}
for(k=0; k<libStatement[i].nums; k++)
{
grade[0][k] = max(grade[0][k-1]-0.5, words[0][k]-0.5*(k-1) );
}
for(k=1;k<temp.nums;k++)
{
for(j=1;j<libStatement[i].nums;j++)
{
grade[k][j] = maxs( grade[k-1][j]-0.5, grade[k][j-1]-0.5, grade[k-1][j-1]+words[k][j] );
}
}
int sum = grade[temp.nums-1][libStatement[i].nums-1];
if(allstorage[textnums].snums < sum)
{
allstorage[textnums].lib = libStatement[i].statement;
allstorage[textnums].snums = sum;
allstorage[textnums].tnums = temp.nums;
allstorage[textnums].text = temp.statement;
}
}
textnums++; //text文件的句子的个数
}else //匹配到空格
{
if( tempStatement=="" )
{
continue;
}
else if(tempStatement[tempStatement.size()==1?1:tempStatement.size()-1] != ' ') //匹配到空格,当前句末不为空格,添加空格
{
tempStatement += " ";
num1 += 1;
}
}
}
infile.close(); //关闭文件输入流
5. 运行结果

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