数据结构代码相似度检测.docx
《数据结构代码相似度检测.docx》由会员分享,可在线阅读,更多相关《数据结构代码相似度检测.docx(6页珍藏版)》请在冰豆网上搜索。
![数据结构代码相似度检测.docx](https://file1.bdocx.com/fileroot1/2023-1/3/b7b90b66-e93f-4aa3-a416-8d23f56dd344/b7b90b66-e93f-4aa3-a416-8d23f56dd3441.gif)
数据结构代码相似度检测
思路:
首先,对要进行比较的所有代码段进行词法分析,并转化为特定的标记(token)串,自己制定一个转换规则。
接着,通过两两比较标记(token)串来确定代码之间的相似性,并由此确定代码之间抄袭的程度,过程如图2.1所示。
图2.1源代码复制检测过程示意图
将这两个代码分别转换为token串后,基于算法RKR-GST(running-karp-rabingreedy-string-tiling)算法思想,循环求取两个标记串中未被匹配部分的最大公共子串,将其用空格代替,并根据如下公式求出两个token串A,B的相似度:
(2.3)
过程论述
流程图
首先要对整个设计做一个整体规划,即设计一个流程图,如图3.1。
图3.1程序流程图
程序清单
#include
#include
#include
#include
#include
#include
#include
#defineN10000
#defineM10000
#defineMAXSTRLEN10000 //定义最大串长
typedefintstatus;
typedefunsignedcharSString[MAXSTRLEN+1]; //串的定长顺序存储表示
SStringa[3]={"int","long","short"};
SStringb[2]={"float","double"};
SStringc[15]={"&&","||","++","--","+","-","*","/","=",">=","<=","==","!
=",">","<"};
SStringd[12]={"[","]","{","}","(",")",",",";","'","#",";","."};
SStringe[29]={"auto","break","case","char","const","continue","default","do","else","enum", "extern","for","goto","if","main","printf","register","return","signed","sizeof", "static","struct","switch","typedef","union","unsigned","void","while","volatile"};
HANDLEhOut;
DWORDwritten;
voidShadowWindowLine(char*str);
chartype(char*str);
voidtoken(charname[],charlist[],chartoken[],FILE*table);
voidsimple(intMinMatchLen,FILE*fp1,FILE*fp2);
statusreplace(SStrings,intpos,intlen,intLs);
intcopy(floatn);
voidShadowWindowLine(char*str)
{
SMALL_RECTrc;
CONSOLE_SCREEN_BUFFER_INFObInfo;//窗口缓冲区信息
WORDatt0,att1,attBack;
inti,chNum=strlen(str);
GetConsoleScreenBufferInfo(hOut,&bInfo);//获取窗口缓冲区信息
//计算显示窗口大小和位置
rc.Left=(bInfo.dwSize.X-chNum)/2-2;
rc.Top=8;//原代码段中此处为bInfo.dwSize.Y/2-2,但是如果您的DOS屏幕有垂直滚动条的话,还需要把滚动条下拉才能看到,为了方便就把它改为10
rc.Right=rc.Left+chNum+4;
rc.Bottom=rc.Top+4;
att0=BACKGROUND_RED|BACKGROUND_BLUE;//阴影属性
att1=FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY|BACKGROUND_RED|BACKGROUND_BLUE|BACKGROUND_INTENSITY;//文本属性
attBack=BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE|BACKGROUND_INTENSITY;//背景属性
//设置阴影然后填充
COORDposShadow={rc.Left+1,rc.Top+1},posText={rc.Left,rc.Top},posBack={0,0};
for(i=0;i<25;i++)
{
FillConsoleOutputAttribute(hOut,attBack,80,posBack,&written);
posBack.Y++;
}
for(i=0;i<5;i++)
{
FillConsoleOutputAttribute(hOut,att0,chNum+4,posShadow,&written);
posShadow.Y++;
}
for(i=0;i<5;i++)
{
FillConsoleOutputAttribute(hOut,att1,chNum+4,posText,&written);
posText.Y++;
}
//写文本和边框
posText.X=rc.Left+2;
posText.Y=rc.Top+2;
WriteConsoleOutputCharacter(hOut,str,strlen(str),posText,&written);
SetConsoleTextAttribute(hOut,bInfo.wAttributes);//恢复原来的属性
}
chartype(char*str) //此函数判断单词类型
{
inti;
for(i=0;i<3;i++) //a中的关键字
{
if(strcmp(str,a[i])==0)
return'K';
}
for(i=0;i<2;i++) //b中的关键字
{
if(strcmp(str,b[i])==0)
return'E';
}
for(i=0;i<15;i++) //c中的符号
{
if(strcmp(str,c[i])==0)
return'A';
}
for(i=0;i<12;i++) //d中符号
{
if(strcmp(str,d[i])==0)
return'R';
}
for(i=0;i<29;i++) //e中的关键字
{
if(strcmp(str,e[i])==0)
return'Y';
}
if(isdigit(str[0])) //0-9是数字
{
return'N';
}
//一般的变量与字符
if(!
isalnum(str[0]))
return'H';
elsereturn'C';//变量
}
voidtoken(charname[],charlist[],chartoken[],FILE*table) //将两个文件中的字符串分别切割转换为token串
{
FILE*in,*out;
charch,c,buffer[N],*link[M];
inti=0,j=0,k=0,LenLink=0;
if((in=fopen(name,"r+"))==NULL)
{
printf("源文件无法打开!
\n");
exit(0);
}
if((out=fopen(list,"w+"))==NULL)
{
printf("文件写入失败!
\n");
exit(0);
}
if((table=fopen(token,"w+"))==NULL)
{
printf("文件写入失败!
\n");
exit(0);
}
while(!
feof(in)) //逐字读取文件
{
ch=fgetc(in);
if(ch=='\t'||ch==''||ch=='\n') //去掉空格、制表符、回车