Clion算法竞赛插件AutoCp的配置与使用(附详细图文讲解)

背景

电脑硬盘坏掉了,送到售后修了整整一周(被迫戒了一周的网瘾),换了块硬盘还彻底丢了数据,在纠结用Sublime和VsCode的时候想看看Clion有没有啥合适的插件,最终发现了Auto CP,并放弃了其他两个环境的搭建

前言

此前我一直使用的是Sublime的cppfastolympiccoding插件进行竞赛代码的快速判题(队友强力推荐的jiangly-like开发环境),此后队里还有使用VsCode写竞赛代码借助CPH插件快速判题的成员,使用体验基本跟Sublime差不多,不过得益于VsCode环境,CPH在UI设计上更胜一筹,但本文重点不在于比对这两个环境,所以不对这两个开发环境进行大量的横向对比,我们将重点放在Clion与其他两个的对比上

先说一下Clion下使用Auto CP相较于Sublime和VsCode以及其他C++ IDE的优点:

  1. 几乎所有XCPC赛事都会提供Clion,在熟悉竞赛环境方面Clion的优势很大
  2. Clion是目前几乎最完整的C++开发环境,相较于其他C++ IDE而言Visual Studio对C++标准支持的不是很好,Code::Blocks现代化程度不高,devc++算彻底的老古董了,Sublime和VsCode不是彻底的C++ IDE,需要安装大量插件,配置起来相当麻烦
  3. Clion的调试功能简单好用,可以很方便地找到代码RE的原因

缺点当然也是要提一下的:

  1. Clion内存占用极高
  2. 有大量竞赛用不上的功能(对于非竞赛选手而言倒算不上缺点)
  3. 因资源占用高导致移动端续航相较于其他轻量级的代码编辑器更低
  4. 对代码风格以及变量命名的要求的强制性高于其他IDE/编辑器(劝退喜欢压行的OI-style代码,将会面对满屏幕的黄色波浪线)

我将从Clion的安装开始介绍,如果你已经安装好了Clion就不需要从Clion安装部分开始看了(太冗长了),可以直接跳到下载插件部分

安装Clion

JetBrains官网可以下载Clion安装包
download
download2
下载完成后直接打开,打开过程比较慢,请耐心等待

打开后点击下一步

install-clion1

大家根据自己情况选择安装路径,这里我就不改了

install-clion2

这边建议把这三项打开,文件关联不用动(一般用非项目方式打开的cpp文件也跑不了,还不如不关联)

install-clion3

install-clion4

安装完之后重启即可(其实不重启也不影响)

install-clion5

install-clion6

初始化Clion

Clion第一次打开会让你选择语言,当然直接选择中文即可

init1

然后统一一下用户条款

init2

数据共享大家根据自己的隐私情况选择

init3

这里假定大家没有Clion的许可证,Clion在2025年开放了非商业免费使用,大家可以直接免费非商业使用,有教育邮箱的话可以去申请教育免费许可证,这里不过多赘述

init4

后续的注册及登录流程不过多赘述

安装MinGW

Clion是自带MinGW的,但是不在环境变量里面,为了保证插件的兼容性,我们需要手动为MinGW配置环境变量

右键桌面上的 Clion 点击 打开文件位置

path3

右键桌面上的 此电脑 点击属性

path

找到高级系统设置

path2

在弹出的窗口中点击 环境变量

path4

在 系统变量 中找到 Path 选项,并点击 编辑

path5

返回刚刚右击Clion后弹出的文件夹窗口,依次点击mingw->bin,然后复制路径

path6

在 编辑环境变量 页面,点击 新建,粘贴复制过去的路径,并点击确定

path7

Clion的基本使用

在获得使用许可后,会进入Clion的欢迎界面,不过不少算法竞赛选手都对项目没有概念,这里顺便介绍一下基本的使用,这里完全面向曾经只使用devc++或VsCode对单一的cpp文件进行编辑,对软件项目没有概念的哪些读者。而有JetBrains IDE使用经验或对软件开发有基础了解的读者可以跳过本节

首先新建一个项目,JetBrains的cpp代码必须在项目中才能运行

init6

然后选择项目的路径及C++标准,OI选手建议C++14,ACM选手建议C++17及以上

一定要选择一个空文件夹,项目一般都是以文件夹为单位进行组织的

init7

接着弹出了项目向导窗口,Clion自带了MinGW,这里直接点击确定即可

init8

然后就可以编写代码了,双击左侧的main.cpp,点击上方的绿色播放键可以运行代码,虫型的按钮可以调试代码

init9

现在编写A+B Problem的代码(如下)进行测试

#include <iostream>  
  
using namespace std;  
int main() {  
    int a,b;  
    cin>>a>>b;  
    cout<<a + b<<endl;  
    return 0;  
}

将main.cpp的内容替换为以上内容,点击运行键,将在下方弹出shell窗口,可以在这里进行标准输入

init10

如果你的代码是手写出来的,一定会注意到Clion有自带的AI插件,对你的下一步代码进行提示(干扰) (辅助作弊),因此强烈建议关闭AI插件,关闭方式如下:
在左上角打开菜单:

init11

然后打开设置

init12

打开 插件 栏,进行如下操作

init13

然后重启Clion

init14

以上步骤将在后文中简化为文件->设置->插件->已安装

下载插件

到这里,大家已经对Clion的使用有了基本的概念了,但是使用运行+控制台输入的方式进行调试,效率相对较低,所以我们安装Auto CP插件及competitive companion浏览器插件,实现高效的数据获取及自动比对

我在这里提供两种安装方法,笔者使用的是在Github下载最新插件并本地安装(截至2025/7/31,插件市场的版本并不支持对拍)

直接在插件市场安装

我在写这个教程的时候,最新版的AutoCp(支持对拍)并没有同步更新至插件市场,请大家看清楚插件版本进行选择,插件市场的版本要是在8.0+可以直接在插件市场下载

可以直接在Clion的插件市场安装Auto CP插件,因提供的Auto CP插件版本较旧,不建议在这里进行安装,后文将讲解如何在Github下载最新版插件

文件->设置->插件->MarketPlace搜索Auto CP后直接点击安装即可

install-plugin1

在github获取最新版插件并手动安装

访问插件的github主页

进入Release页面:

install-plugin2

install-plugin3

点击下载插件后,在文件->设置->插件界面,点击齿轮,从磁盘安装插件,从本地选择刚刚下载的压缩包进行安装

install-plugin4

随后就可以在右侧看到插件的图标了

install-plugin5

在安装完插件后一定要重启Clion

Competitive Companion安装

Competitive Companion下载地址(chrome应用商店)为浏览器安装扩展,以便为AutoCp获取竞赛的测试样例

无法打开chrome应用商店的读者可以使用国内镜像站Competitive Companion下载地址(chrome国内镜像站)

安装后会在浏览器插件栏显示,建议固定到地址栏旁边方便使用

install-plugin6

使用Auto Cp进行判题

前面用大量的篇幅介绍了怎么安装Clion、安装Auto Cp,安装Competitive Companion,接下来该讲述怎么使用Auto Cp做题了

首先打开一道CF题目(或者其他OJ平台都可以)Codeforces题目链接,我们点击固定在地址栏的 Competitive Companion图标

接着返回Clion,可以看到弹出了一个窗口,我们直接点击确定

getsample1

我们注意到,AutoCp为我们新建了一个源文件,同时左侧有新建的文件夹

getsample2

第一次使用这个插件,必须使用右键->运行->题目名来运行(可能是因为Bug,博主第一次使用快捷键会报错,在手动运行一次后就可以使用快捷键了),之后就可以使用快捷键Alt + X进行调试了

run1

评测结果将在下面显示,如果评测结果正确将显示如下:

run2

如果有错误的测试点,将显示如下:

run3

将下方的控制台窗口滚动至底层,可以看到一个<点击以查看差异>的超链接,点击后可以将我们的输出与测试样例输出进行一个直观的对比:

run4

要编辑测试点,可以打开右侧的插件栏

run5

此外,Auto Cp支持使用Competitive Companion对整个竞赛进行解析,只需要我们在题目页点击Competitive Companion的按钮:

getsample3

之后Auto Cp将会创建所有比赛的源码模板以及获取测试点:

getsample4

点击确定即可,用法同上

编辑代码模板

Auto Cp对每个题自动生成的模板,可能让不少人对此并不满意,当然模板是可以自定义的

打开菜单->文件->设置->编辑器->文件和代码模板->其他->AutoCp Templates->CP_TEMPLATE_CPP.cpp就可以看到AutoCp默认提供的C++模板如下:

//  ${PROBLEM_NAME}

#[[#include]]#<bits/stdc++.h>

using namespace std;

int main() {
    $END
    return 0;
}

因为#在JetBrains的模板体系里面有特殊用途,所以涉及到#的cpp代码使用了#[[#include]]#进行转义
#外,注释里的${PROBLEM_NAME}是模板生成时根据编译器环境自动填充的常量,常量表如下:
以下是Auto Cp插件提供的常量

常量 内容
${PROBLEM_GROUP_NAME} 竞赛名称
${PROBLEM_NAME} 当前源文件对应的问题名
${ONLINE_JUDGE_NAME} 当前源文件对应的OJ名

以下是JetBrains提供的常量:

常量 内容
${CALL_SUPER} 覆盖生成期间的基本函数调用签名
${DATE} 当前系统日期
${DAY} 当前日期
${DEFAULT_RETURN_VALUE} 函数的默认返回值
${DIR_PATH} 新文件所在目录的路径(相对于项目根目录)
${DS}|美元符号 $。 该变量用于转义美元符号,使其不被视为模板变量的前缀。
${FILE_NAME} 新建 C 或 C++ 文件的名称
${HEADER_COMMENTS} 始终返回 true ,用于测试目的
${HEADER_FILENAME} 为类或源文件生成的头文件名称
${HOUR} 当前小时
${INCLUDE_GUARD} 防止重复包含特定头文件
${MINUTE} 当前分钟
${SECOND} 当前秒
${MONTH} 当前月份
${MONTH_NAME_FULL} 当前月份的全名(如一月、二月等)
${MONTH_NAME_SHORT} 当前月份名称的前三个字母(如 Jan、Feb 等)
${NAME} 新实体的名称(文件、类、接口等)
${NAMESPACE_CLOSE} 重构期间创建的命名空间块的结束
${NAMESPACE_OPEN} 重构期间创建的命名空间块的开始
${PRODUCT_NAME} IDE 名称(例如,CLion)
${PROJECT_NAME} 当前项目名称
${RETURN_TYPE} 函数返回值的类型(用于生成新函数)
${SUIT_NAME} Google 测试套件名称
${TEST_NAME} Google 测试名称
${TIME} 当前系统时间
${USER} 当前用户的登录名(所有平台)
${USER_NAME} 对于 Windows 和 Linux:当前用户的登录名

对于 macOS:用户注册的全名
${YEAR} 当前年份

JetBrains还提供了更复杂的模板语法,在此不过多赘述,我将我使用的模板分享出来:

//  ${ONLINE_JUDGE_NAME} contest ${PROBLEM_GROUP_NAME} ${PROBLEM_NAME}
//  Created at ${DAY}.${MONTH}.${YEAR} ${HOUR}:${MINUTE}:${SECOND} in file ${FILE_NAME}
//  By ${USER}
#[[#include]]#<iostream>
#[[#include]]#<vector>
#[[#include]]#<algorithm>
#[[#include]]#<cstdlib>
#[[#include]]#<cassert>
#[[#include]]#<iomanip>
#[[#include]]#<climits>
#[[#include]]#<functional>
#[[#include]]#<numeric>
#[[#define]]# ENDL endl
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
std::istream& CIN = std::cin;
std::ostream& COUT = std::cout;
using namespace std;
const int MOD = 1e9+7;

void solve(){
    $END
}

int main() {
    int tt = 1;
    cin.tie(nullptr);
    cin.sync_with_stdio(false);
    cout.tie(nullptr);
    cout.sync_with_stdio(false);
    cin>>tt;
    //freopen("case1.in","r",stdin);
    //freopen("case1.out","w",stdout);
    while(tt--){
        solve();
    }
    return 0;
}

使用Auto Cp对代码进行对拍

Auto Cp自带的对拍器,可以让我们很方便的生成测试数据,对当前代码进行压力测试,这个是Auto Cp相较于cppfastolympiccoding和cph插件最大的独特之处

我们先来讲解不需要Checker的情况下该怎么使用这个对拍
假如我们对一个A + B Problem进行对拍:

题目描述:

输入两个整数A和B,输出A + B的值

输入格式:

对于每组测试样例,输入两个整数\(A,B(1 \leq A \leq 10^{12},1 \leq B \leq 10^{12}\)

输出格式:

对于每组测试样例,输出1个整数,代表两数相加的结果

输入样例1:

1 2

输出样例1:

3

这是一道最经典的用于测试OnlineJudge输入输出功能的题目,接下来我们先给出会被Hack的解法,这个解法是在A+B.cpp文件里面写的,我们的目标是通过对拍找到这个解法的错误之处:

#include <iostream>  
using namespace std;  
  
int main(){  
    int a,b;  
    cin>>a>>b;  
    cout<<a+b<<endl;  
    return 0;  
}

Auto Cp会自动在每次运行对拍器时输入一个整数,代表现在是第几次的代码压力测试,我们可以借助这个整数作为随机数生成种子

根据题目测试样例,我们需要相应的使用随机数生成数据,在此我们借助mt19937随机数生成器进行数据生成,答案使用标准输出即可

#include <iostream>
#include <random>
using namespace std;
int main(){
	int n;
	cin>>n;
	mt19937_64 rand(n);
	long long a = rand() % (long long)1e12 + 1;
	long long b = rand() % (long long)1e12 + 1;
	cout<<a<<' '<<b<<endl;
}

接着我们还需要另一个可以写出来的任意解法,这个任意解法不受时间和空间限制,换而言之我们使用这个任意解法生成正确数据,并通过与原程序的输出进行对比,来判断程序的正确性

当然A + B这个问题,我也没什么其他解法了,上述程序无法AC的原因很明显,没有开long long,但我们讨论的问题是,如何生成正确答案,我无法给出其他任意解法,直接放正解作为对拍的数据生成器了

#include <iostream>  
using namespace std;  
  
int main(){  
    long long a,b;  
    cin>>a>>b;  
    cout<<a+b<<endl;  
    return 0;  
}

我们现在准备好了数据生成代码和不受时间和空间限制的一个解法,接着我们把他们分别放进插件菜单栏->Generetor->Generator program code插件菜单栏->Generetor->Solution program code

generator1

在跑到第一个失败样例后,将会出现错误提示,并给出测试数据内容:

generator2

假定我们找到代码的错误原因,并通过修改得到了正解,再执行压力测试,将会得到以下结果:

generator3

接着是需要Checker的情况下,该怎么编写这个checker

假如我们有这么一道简单的构造题:

题目描述:

构造一个长度为\(n\)的数组\(a\):

  1. 数组中任意两个数字的最大公约数为1
  2. 数组中没有重复元素

输入格式:

对于每组测试样例,输入一个整数\(n(1 \leq n \leq 10^4)\)

输出格式:

对于每组测试样例,输出\(n\)个整数,代表构造出来的数组

输入样例1:

5

输出样例1:

2 3 5 7 11

这道题的思路相当简单,只需要构建一个全质数的序列就可以了, 但是如果有参赛选手不愿构造从2开头的质数序列,使用类似3 5 11 17 2的输出,我们也不能将其判错,这时候就需要checker了

要判断选手的输出是否正确其实很简单,只要模拟一遍题意,看是否存在两数gcd不为1即可

我们先思考,要评测一个题目,至少需要哪些输入和输出

  • 测试点原输入内容,因为这些内容可能包含数组大小等信息
  • 测试代码的输出内容,要判断这个输出是否正确,肯定少不了这个内容
    可能需要的内容:
  • 程序正解的输出内容
    需要Checker提供的内容
  • 检查后的结果正确与否
    在知道Checker需要与哪些内容打交道后,我们将Auto Cp的Checker体系融入:
  • 测试点原输入内容在:input.txt
  • 测试代码的输出内容在:answer.txt
  • 程序正解的输出内容在:correct.txt
  • 检查后的结果正确与否在:return,答案错误返回1,正确返回0
    过去相比有不少算法竞赛选手使用freopen函数,来借助标准输入输出流避免直接和文件打交道,但这个Checker需要跟四个文件打交道,所以freopen函数我个人是不建议使用的

我将直接使用fstream流从文件读取和输出

那么,我们从上面提供的文件实现判题思路如下:

#include <fstream>
#include <numeric>
#include <vector>
using namespace std;
int main()
{
    ifstream input("input.txt");
    ifstream answer("answer.txt");
    ifstream correct("correct.txt");
    ofstream comment("comment.txt");
    int n;
    input>>n;
    vector<int> a(n);
    for(int i=0;i<n;i++)
    {
        answer>>a[i];
    }
    for (int i = 0;i<n;i++)
    {
        for (int j = i+1;j<n;j++)
        {
            if (gcd(a[i],a[j]) != 1)
            {
                return 1;
            }
        }
    }
    return 0;
}

将以上代码填入插件菜单栏->Judge->Judge program code

checker2

同时提供生成器和正解:

#include <iostream>
#include <random>
using namespace std;
int main(){
	int n;
	cin>>n;
	mt19937_64 rand(n);
	int nn = rand() % int(1e4);
	cout<<nn<<endl;
}
#include <iostream>
#include <vector>
using namespace std;  
std::vector<int> minp, primes;

void sieve(int n) {
    minp.assign(n + 1, 0);
    primes.clear();
    
    for (int i = 2; i <= n; i++) {
        if (minp[i] == 0) {
            minp[i] = i;
            primes.push_back(i);
        }
        
        for (auto p : primes) {
            if (i * p > n) {
                break;
            }
            minp[i * p] = p;
            if (p == minp[i]) {
                break;
            }
        }
    }
}
int main(){  
    int n;
    cin>>n;
    sieve(4e5);
    for(int i = 0;i<n;i++){
        cout<<primes[i]<<' ';
    }
    cout<<endl;
    return 0;  
}

以及我提供的,用户的意料之外的解法,从3开始输出质数,而不是正解所提供的2开始:

#include <iostream>  
#include <vector>  
using namespace std;  
std::vector<int> minp, primes;  
  
void sieve(int n) {  
    minp.assign(n + 1, 0);  
    primes.clear();  
  
    for (int i = 2; i <= n; i++) {  
        if (minp[i] == 0) {  
            minp[i] = i;  
            primes.push_back(i);  
        }  
  
        for (auto p : primes) {  
            if (i * p > n) {  
                break;  
            }  
            minp[i * p] = p;  
            if (p == minp[i]) {  
                break;  
            }  
        }  
    }  
}  
int main(){  
    int n;  
    cin>>n;  
    sieve(4e5);  
    for(int i = 1;i<=n;i++){  
        cout<<primes[i]<<' ';  
    }  
    cout<<endl;  
    return 0;  
}

按下Alt + Shift + X开始进行压力测试,最终用户的不被期望的解如果通过测试,将得到以下内容:

checker3

如果没有通过测试,将会得到以下反馈:

checker1

至于交互题?我还是绿名蒟蒻,交互题该怎么使用这个插件就靠大家自己研究了(逃

posted @ 2025-07-31 01:00  ClauBloom  阅读(510)  评论(1)    收藏  举报