简介SIMGUI 是一款基于 Electron 与 Element UI 开发的 C/Python 代码查重工具面向高校教师、研究者和开发团队用于检测源代码相似度、辅助作业查重与代码质量管理。软件核心集成开源 SIM 算法通过可交互界面完成代码导入、查重参数调整、相似区域比对和结果导出使用者无需了解算法底层细节。压缩包共 87 个文件约 70MB主要包含 exe 主程序、dll 运行库、pak 界面与语言资源、png 操作示例图以及 bin/json 等配置文件解压后即可运行。依托 Electron该工具支持 Windows、macOS、Linux 等常见系统。发布页已有 530 人学习下载适合需要快速识别重复代码、规避抄袭风险并促进代码优化的场景。本地免安装运行还能减少对源码隐私的暴露即使离线也可完成检测报告会清晰列出相似代码块便于逐段审查与后续重构。1. SIMGUI 代码查重免安装版解压即用但先看懂它是怎么查的期末交 C 大作业那几天实验室里总有人在传一个绿色小工具SIMGUI 代码查重免安装版。你把它解压到 U 盘里双击就能用把全班作业按学号放好点两下鼠标就生成一份相似度报告——被怀疑互相抄袭的学号整整齐齐排在表头。它本质上是本地查重引擎 SIMSoftware Integrity Measurement的图形界面封装sim_c 和 sim_py 分别负责 C/C 和 Python所有比较都在本机完成不联网、不上传代码。对助教、项目负责人、外包验收的人来说这是最省事的一条路。但“免安装”三个字容易让人放松警惕它省掉的是安装流程不是运行时依赖后面一半的坑都出在这里。这篇笔记就按“原理怎么跑、命令怎么敲、报告怎么读、参数怎么调、坑在哪”的顺序讲完。2. 查重原理token 流与公共子串匹配C 和 Python 的差异在哪2.1 从源码到 token 流注释被丢掉空白折叠标识符保留SIM 不直接比较“两行文本是否相同”因为字符级比较太容易被伪装骗过去你只要把整段代码换行、重新缩进每一行都变了行级比较就失灵了。所以 SIM 第一步是把源码喂给内置的词法分析器切成 token 流。token 是源码的语义最小单元关键字、标识符、数字、字符串、运算符各算一个 token。比如for (int i 0; i n; i)会被切成一串for(inti0;in;i)。比较就在这串 token 上进行而不是在原始文本上进行。token 化过程中有三个归一化动作直接决定它能抓什么第一空白和换行被折叠所以“把代码重排缩进”在这个工具面前基本无效第二注释默认被跳过所以“删掉注释再交”也不会降低相似度第三标识符保留原名。这一点和很多人的直觉不一样SIM 不会像某些在线查重系统那样把所有变量名抽象成同一个记号所以“把 a 改成 b、把函数名整体换一遍”这种操作确实能降低 SIM 的分数。这也是为什么 SIM 的报告不能直接当判罚依据——它筛出来的东西需要人工再扫一遍。你可以把这理解为黑匣子的一个已知盲区机械改名能骗过它但语义等价重写更能骗过它。2.2 公共子串匹配最小匹配长度决定误报与漏报拿到 token 流之后SIM 对每两个文件做一次两两比较寻找足够长的公共 token 子串。这个“足够长”就是参数-r的物理意义连续多少个 token 完全一致才算一次有效匹配。-r取太小for (int i 0;这种任何两个写 C 的人都会撞车的三五个 token 也会被算进去全班相似度轻松破 40%报告失去区分度-r取太大故意穿插修改的长代码块又匹配不上漏报严重。每个匹配片段都带坐标在哪个文件第几行到第几行所以报告绝不是孤零零一个百分比而是“哪些地方像像到什么程度”。相似度的计算口径是文件里所有被匹配的 token 数占这个文件总 token 数的比例。因为两份文件长度不一定相同所以一对文件会有两个百分比通常不对称。还要记住一点SIM 是切片级相似检测不是语义查重它抓不到“按语义完全重写”的代码。这是工具边界不是版本缺陷。实操里有一个很常见的结构值得注意如果 A 和 B 都抄了同一份源文件 C报告往往出现 A-C 很高、B-C 也很高但 A-B 反而低的现象——因为 A 和 B 各自改了不同的变量名和插入位置。只看最高分对会漏掉这种星型抄袭结构正确做法是把所有超过阈值的对全部扫一遍。2.3 C 与 Python 的 token 化差异参数默认值为什么不一样C 的 token 流里符号 token 特别多分号、括号、花括号、双冒号、模板尖括号到处都是预处理指令#include还会把一整行公共内容变成 token 参与比较。这带来的直接后果是C 查重必须先处理公共头文件否则每个人#include iostream和 using 声明本身就贡献了大量公共 token基线相似度被无谓抬高。我一般会建一个common.txt排除清单把课程提供的模板头文件、公共框架代码全部列进去再做正式比对。Python 的情况相反关键字密度高、符号 token 少、没有预处理器缩进被折叠之后代码块结构主要通过defclassiffor这些关键字体现。相同逻辑的两段 Python切出来的 token 序列更像自然语言的句子匹配片段往往更长、更完整所以-r可以比 C 取更大。我的经验值是C/C 用-r 5左右Python 用-r 10左右。这两个不是官方默认值是根据 token 流密度调出来的经验值后面讲调参时会说明怎么根据报告反推。免安装包不会替你区分这些差异——GUI 让你选语言本质就是帮你选调用哪个核心程序。2.4 免安装版的内部构成GUI 前端只是传话人社区里叫 SIMGUI 的封装版本很多但结构大同小异本质都是“图形前端 命令行核心”。你双击的 GUI 不实现任何查重算法它只做三件事收集参数、调用核心 exe、渲染报告。SIMGUI/ ├─ SIMGUI.exe # 图形前端常见为 .NET/WinForms 或 Delphi 编写 ├─ sim_c.exe # C/C 查重核心 ├─ sim_py.exe # Python 查重核心 ├─ sim_java.exe # Java 查重核心 ├─ sim_text.exe # 纯文本查重核心 ├─ config.ini # 前端持久化语言、阈值、运行长度 └─ report/ # 报告输出目录部分版本直接在界面里展示判断一个免安装版是否完整第一件事就是核对这份核心程序清单。很多人下载的版本只带了 GUI 和 sim_c.exe切到 Python 查重时界面毫无反应——那是因为 sim_py.exe 压根不存在。免安装的真正价值是不写注册表、不装系统服务、删掉目录就是卸载适合教学机房和 U 盘场景。但要注意GUI 和核心程序大多是用 MSVC 或 .NET 编译的运行仍依赖 Microsoft Visual C 运行库最常见的是 2015-2022 Redistributable (x64)。Win10/11 多半自带或能快速补装老系统则经常在这里翻车这一条到第 5 章避坑部分展开。3. 免安装版实操用 sim_c / sim_py 跑通第一次代码查重3.1 拿到免安装版后先确认四件事无论从哪个渠道拿到的包先别急着双击 GUI。我一般会做四步确认能省掉后面两个小时的问题排查。第一核对 2.4 里的目录清单确认你要用的语言核心 exe 在不在。第二在免安装版目录里开一个 cmd 窗口直接执行sim_c.exe -h能打印一屏英文帮助说明运行库正常如果报“缺少 VCRUNTIME140.dll”或“找不到 MSVCP140.dll”说明机器缺 VC 运行库先去装 Microsoft Visual C 2015-2022 Redistributable (x64)。第三把所有路径改成纯英文GUI 和核心程序经常按 ANSI 编码解析参数中文路径会产生大量“找不到文件”的玄学问题。第四源文件统一保存为 UTF-8 无 BOMC 源文件里如果有 GBK 编码的中文注释建议先转码再跑否则可能出现“文件读不进去但程序不报错”的静默跳过。这里顺便回一个高频误区很多人以为跑 sim_py 需要先装 Python 解释器甚至要先配置 vscode 的 C/C 环境——完全不需要。sim_py.exe 是编译好的独立程序它对 Python 源码做词法分析是在自己进程里完成的你机器上有没有 Python 都不影响。需要 Python 的场景只有一个你想写批处理脚本批量调用这些 exe那是另一回事第 6 章会讲。3.2 第一个查重命令C 全目录跑通确认完四件事后用命令行跑通一次是最稳妥的。假设所有待查的.c/.cpp文件都在D:\submissions下面公共模板清单是common.txtcd /d C:\CheckTool sim_c.exe -t 30 -r 5 -e common.txt D:\submissions\*.c D:\submissions\*.cpp report_c.txt这条命令做了四件事-t 30只显示相似度大于等于 30% 的文件对避免输出文件大到没法翻-r 5表示 5 个连续 token 以上的匹配才算数对应 C 场景的常用最小匹配长度-e common.txt把公共模板从头文件集合里排除 report_c.txt把结果落盘。跑完之后打开 report_c.txt第一屏应该是“Comparing: 文件名列表”往下是每一对文件的百分比和匹配片段坐标。一个容易翻车的细节cmd 命令里的D:\submissions\*.c是否生效取决于 sim_c.exe 自己有没有内置通配符展开逻辑。老版本工具经常没有结果是把*.c当成一个普通文件名处理然后报“无法打开文件”。遇到这种情况不要硬磕 cmd换 PowerShell 把文件列表先展开成数组再传给命令$files Get-ChildItem -Path D:\submissions -Include *.c,*.cpp -Recurse | Select-Object -ExpandProperty FullName .\sim_c.exe -t 30 -r 5 -e common.txt $files | Out-File report_c.txt -Encoding utf8这里Get-ChildItem -Recurse顺带解决了另一个常见的 GUI 短板——很多免安装版的图形界面不支持递归子目录只扫当前文件夹而命令行配合 PowerShell 可以一次性把子目录里的文件全部卷进来。PowerShell 的数组传参也是真实可用的$files会被自动展开成多个命令行参数。Python 的首次运行同理只需换核心程序和-r取值sim_py.exe -t 30 -r 10 -e common.txt D:\submissions\*.py report_py.txtPython 的-r 10依据在 2.3 里说过它的 token 流更稀疏公共语法片段更短-r太小会误报泛滥。跑完先不要调任何参数直接看报告。3.3 必调参数-r 最小匹配长度、-t 阈值与 -e 排除清单参数 作用 常见取值 -r N 连续 N 个 token 完全一致才算匹配 C/C3~8Python8~15 -t N 只显示相似度 N% 的文件对 初筛 20~30坐实 60 以上 -e FILE 排除清单每行一个文件名 公共头文件、课程模板、框架代码三个参数里最容易调反的是-r。它要的是“连续匹配的 token 数”不是文件行数也不是百分比。很多 GUI 封装把它标成 “min run length” 或 “detection size”填的时候一定要先弄清单位。-t填的是 0 到 100 的百分比不是 0 到 1 的小数——有人填过 0.3结果所有相似度大于 0.3% 的对全显示出来报告上万行。参数填完之后先拿一个只有两个文件的小目录试跑用肉眼确认输出和预期一致再上全量。这一步是验证 GUI 有没有把参数正确传给核心程序的关键也是发现封装 bug 最快的路径。如果 GUI 不支持-e排除清单不必硬解配置文件。更省事的做法是把公共模板文件从待查目录里移出去单独放一个_common目录不参与扫描再建一个只包含学生提交文件的临时目录跑查重。这样既绕开了 GUI 的功能缺口也让报告里的百分比更有解释力。4. 报告解读与阈值判定相似度百分比怎么用才不冤枉人4.1 读报告的三个关键字段百分比对、片段坐标、覆盖占比命令行核心输出的文本报告结构大致如下字段顺序在不同版本里略有差异核心信息一致sim_c -t 30 -r 5 Comparing: A021.cpp, A033.cpp, B002.cpp A021.cpp and A033.cpp: 48% (A021: 52%, A033: 45%) fragment: 41 tokens, lines 23-64 in A021.cpp, lines 31-72 in A033.cpp A021.cpp and B002.cpp: 12% (A021: 11%, B002: 14%)第一行百分比是这对文件的整体相似度括号里是两个文件各自的覆盖占比——A021 有 52% 的 token 被匹配A033 是 45%。不对称是正常的因为两份文件长度不同同一次匹配在长文件里占比低、在短文件里占比高。第二段 fragment 是复核凭证哪两个文件、多少 token、各自在哪几行。我拿到报告时第一眼永远看 fragment 的位置分布而不是整体百分比。如果所有匹配都集中在文件尾部的公共工具函数区说明是共享代码如果从文件中部到结尾连续三四个 fragment 咬合那才是真问题。这里再强调一次星型结构A 和 B 都抄 C 时报告会出现 A-C 高、B-C 高、A-B 低。所以不要只盯着百分比最高的那一对文件看把所有超过阈值的对先列成一张表按“公共源文件”角度再扫一遍能发现很多隐藏关系。4.2 阈值分档30% 是分水岭60% 基本坐实场景 建议阈值 处理动作 课程作业初筛 30% 进入人工复核 课程作业坐实 60% 直接列为重点检查对象 项目交接审查 20% 更低阈值防止改名后混入 开源合规审查 不用总分 只看匹配片段本身课程作业场景里 30% 是我习惯的初筛分水岭低于 30% 的文件对除了极个别的短文件大部分是公共模板和相似题设造成的自然重合30% 到 60% 是灰色地带需要人工打开两个文件并排看60% 以上通常是“整段复制 少量变量改名”可以直接纳入定性流程。项目交接或外包代码审查我会把阈值降到 20%因为这种场景的目标不是抓“完全一样的复制”而是抓“改了名字但结构没动”的继承代码——阈值太高会把这一类漏掉。开源合规审查完全反过来百分比不重要哪怕总相似度只有 15%只要有一个 500 行的函数和某个 GPL 项目的实现逐行匹配风险就比 60% 的课程作业严重得多。这种场景把 fragment 导航当主角百分比当配角。4.3 GUI 与命令行互查怀疑报告时用核心程序复跑GUI 和命令行核心是同一个引擎参数传对时结果必须一致。所以收到一份可疑报告时我做的第一件事不是改参数而是用命令行把同一批文件、同一组参数复跑一遍对比两份报告。数字一致说明 GUI 的封装没问题报告可信数字不一致优先查两件事GUI 是否在背后帮你加了排除规则或者 GUI 是否递归扫描了子目录导致文件集合比命令行多。定位到这个层面问题基本就清晰了——不是查重算法坏了是“喂给算法的文件集合”和“你心里想的文件集合”不一致。还有一个低成本的双引擎交叉验证当 sim_c 给出 30% 左右的可疑分数但匹配片段集中在注释和文档字符串里时用 sim_text.exe 对同一对文件跑一次纯文本查重。sim_text 不做语法归一化它把文本当普通 token 流比较如果 sim_text 的匹配片段与 sim_c 的重合度很低说明刚才的相似来自公共注释和模板框架属于误报。这个“怀疑报告就先复跑”的习惯能省掉大量和工具搏斗的时间。5. 免安装版避坑运行库、中文路径与误报漏报的五个现场5.1 启动阶段缺运行库、被杀毒拦截、核心文件缺失现场一双击 GUI 没反应或者弹窗提示“找不到 VCRUNTIME140.dll”“无法启动此程序因为计算机中丢失 MSVCP140.dll”。原因基本是核心程序用 MSVC 编译动态链接了 VC 运行库而免安装版通常不会把这部分运行库打进去。解决方法是先装一遍 Microsoft Visual C 2015-2022 Redistributable (x64)装完再双击如果还崩就别折腾 GUI 了直接在 cmd 里跑sim_c.exe -h核心能跑就说明问题出在前端而不是运行库。现场二解压后被杀毒软件直接隔离删除或者 Windows SmartScreen 弹蓝色警告。原因很好理解免安装版是无代码签名的自解压程序行为特征和捆绑包有点像启发式规则容易误判。解决方法是把整个目录加入信任区然后用 zip 格式重新分发——zip 比自解压 exe 的误报率低很多。在团队内部更靠谱的做法是把这种免安装工具放进内部软件源统一管理免得每次换机器都有人被拦。现场三GUI 能正常打开但点“开始查重”后报告为空或直接闪退。先核对目录里到底有没有 sim_py.exe、sim_java.exe——很多精简版只带 C/C 核心。另一个高频原因是免安装包被解压到了含空格的路径GUI 拼接命令行参数时把路径切断核心程序找不到文件。把整个目录挪到C:\CheckTool这种无空格路径下再跑能解决一大半“莫名其妙闪退”的问题。5.2 结果阶段中文路径、公共代码、编码导致误报漏报现场四命令行传中文目录提示找不到文件或者报告里的文件名全是乱码。原因是老版本核心程序按系统 ANSI 编码解析路径和文件名中文目录在参数传递过程中被截断。别指望它能修直接批量把待查文件复制到英文路径文件名统一改成学号或编号这是最快的解。报告乱码不影响查重数据本身但要归档留证时很难看顺手改掉更省心。现场五所有文件两两相似度都超过 40%报告完全失去区分度。原因是每个作业都#include同一套头文件、粘贴了同一份课程模板公共 token 全被计入匹配。解决方法是把公共模板提取出来用-e common.txt排除如果 GUI 不支持排除就按 3.3 说的把公共文件移出待查目录。这里有个判断技巧排除公共代码后分数从 50% 掉到 20% 以下说明原本的相似主要来自框架如果排除后仍然在 40% 以上那就是真实复制不用再怀疑工具误报。现场六两份明显复制的 Python 代码分数很低甚至报告里找不到某个.py文件。原因通常是文件带 UTF-8 BOM或者缩进混用了 tab 和空格sim_py 的词法分析器中途解析异常直接把文件跳过。解决方法是先跑一个预处理脚本统一转码并清理缩进from pathlib import Path for p in Path(D:/submissions).rglob(*.py): data p.read_bytes().decode(utf-8-sig, errorsreplace) p.write_text(data.replace(\t, ), encodingutf-8)utf-8-sig解码会同时吃掉 BOMreplace把坏字符替换成占位符而不是中断处理tab 统一成四个空格能减少混合缩进导致的解析波动。这个脚本只做文本层面的规整不改代码语义跑完再执行 3.2 的 sim_py 命令。如果某个文件仍然解析异常就用 sim_text.exe 对它单独兜底别让一个坏文件影响整体结论。6. SIMGUI 进阶两轮阈值法与批量查重的校准技巧6.1 两轮阈值法直接设一个固定阈值做全量筛查总会两头受气阈值太高漏掉灰色地带阈值太低输出几百页没法看。我现在的做法是两轮第一轮-t 20全量扫一遍把结果落成 CSV第二轮把超过 60% 的对单独复查20% 到 60% 的区间按 fragment 分布抽样看。第一轮负责“不漏”第二轮负责“定责”中间灰色地带用人工判断而不是让工具替你拍板。6.2 批量比对与校准实验几十个文件有时需要批量调用核心 exe 并把分数收集成表格可以用一小段 Python 脚本完成import glob, re, subprocess, csv core rC:\CheckTool\sim_c.exe files glob.glob(rD:\submissions\*.cpp) rows [] for i in range(len(files)): for j in range(i 1, len(files)): out subprocess.run( [core, -t, 20, -r, 5, files[i], files[j]], capture_outputTrue, textTrue, errorsreplace ).stdout m re.search(r(\d)%, out) if m: rows.append([files[i], files[j], int(m.group(1))]) with open(result.csv, w, newline) as f: w csv.writer(f) w.writerow([a, b, similarity]) w.writerows(rows)这是示意脚本正则的字段要按你手上版本的输出格式调但两两比对的思路通用。注意复杂度是 O(n²)几十个文件没问题几百个就要先按目录或题目分组再算。脚本跑完前先做一次校准实验拿一份干净的参考程序生成三个变体——只删注释重排缩进的、系统改变量名的、改常量并拆函数的放进一个小目录单独跑。看这三份变体相对原文件的分数梯度是否符合直觉第一个变体应接近满分第二个明显下降但能识别第三个可能跌破阈值。这组实验能告诉你手上这个包的实际灵敏度也顺便验证-r和-t取值是否适合你的题目场景。我现在每次拿到新版本的免安装 SIMGUI第一件事就是在 cmd 里跑sim_c.exe -h再跑一遍校准样本确认黑匣子的行为和预期一致才敢让它进正式流程。希望帮到你。本文还有配套的精品资源点击获取