打 CF 就用 cf-tool[1] ~ 可是命令字母太多了,对拍也不方便

所以就有了做一个把对拍和 cf-tool 集合到一起的工具的想法

前置知识

C++命令行传参方式

#include <bits/stdc++.h>

using namespace std;

int main(int argc, char* argv[]) {
    // your code here

    return 0;
}

命令行传参也就是向上面那样子,main函数里写多点东西就行了

代码

话不多说,代码奉上。

#include <bits/stdc++.h>

using namespace std;

int main(int argc, char* argv[]) {
    if (argc < 2) {
        puts("Command needed.");
        return EXIT_FAILURE;
    }

    string op = argv[1];
    if (op == "-h") {
        if (argc <= 2) {
            string s = argv[2];
            if (s == "-n" || s == "new") puts("-n name: Create a new problem. (Files inside the dictionary: name.cpp, in1.txt, ans1.txt)");
            if (s == "-a" || s == "add") puts("-a number: Add new samples to the problem. (Files added: in{number}.txt ans{number}.txt))");
            if (s == "-c" || s == "check") puts("-c name: Make stress. (Filename: {name}.cpp {name}_sol.cpp gen.cpp)");
            if (s == "-cls" || s == "clear") puts("-cls name: clear");
            if (s == "-v" || s == "view") puts("-v number: View the sample. (in{number}.txt ans{number}.txt)");
            if (s == "-g" || s == "generate") puts("-g: Generate .cpp file.");
        } else {
            puts("-n(new) name: Create a new problem. (Files inside the dictionary: name.cpp, in1.txt, ans1.txt)");
            puts("-a(add) number: Add new samples to the problem. (Files added: in{number}.txt ans{number}.txt))");
            puts("-c(check) name: Make stress. (Filename: {name}.cpp {name}_sol.cpp gen.cpp)");
            puts("-cls(clear) name: clear");
            puts("-v(view) number: View the sample. (in{number}.txt ans{number}.txt)");
            puts("-g(generate): Generate .cpp file.");
        }
    } else if (op == "-n" || op == "new") {
        for (int i = 2; i <= argc; ++i) {
            if (argv[i] == nullptr) {
                continue;
            }
            string s = argv[i];
            system(("mkdir " + s + " && cd " + s + " && touch in1.txt ans1.txt && cp ~/path/to/template.cpp " + s + ".cpp").c_str());
        }
    } else if (op == "-t" || op == "test") {
        int f = 1;
        if (argc == 2 && (argv[2] == "-d" || argv[2] == "-D" || argv[2] == "-debug")) {
            f = 0;
        }
        system("cf test");
        if (!f) {
            system("bat log.txt");
            // system("cat log.txt");
        }
    } else if (op == "-a" || op == "add") {
        for (int i = 2; i <= argc; ++i) {
            if (argv[i] == nullptr) {
                continue;
            }
            string s = argv[i];
            system(("touch in" + s + ".txt ans" + s + ".txt").c_str());
        }
    } else if (op == "-c" || op == "check") {
        for (int i = 2; i <= argc; ++i){
            if (argv[i] == nullptr) {
                continue;
            }
            string s = argv[i];
            system(("g++-12 " + s + ".cpp " + "-o " + s + " " + "-std=c++14").c_str());
            system(("g++-12 " + s + "_sol.cpp " + "-o " + s + "_ac" + " " + "-std=c++14").c_str());
            system("g++-12 gen.cpp -o gen -std=c++14 -O2 -lm");
            int cnt = 0;
            // puts("Started");
            while (true) {
                system("./gen > in.txt");
                clock_t b = clock();
                system(("./" + s + " < in.txt > sol.txt").c_str());
                clock_t e = clock();
                system(("./" + s + "_ac < in.txt > ac.txt").c_str());
                if (system("diff sol.txt ac.txt -b -B")) {
                    printf("\033[31mWrong Answer\033[m #%d\n", ++cnt); 
                    break;
                } else printf("\033[32mAccepted\033[m #%d ... %dms\n", ++cnt, (e - b) / 12);
            }
        }
    } else if (op == "-cls" || op == "clear") {
        for (int i = 2; i <= argc; ++i){
            if (argv[i] == nullptr) {
                continue;
            }
            string s = argv[i];
            system(("rm " + s + " " + s + "_ac gen in sol sol_ac").c_str());
        }
    } else if (op == "-v" || op == "view") {
        for (int i = 2; i <= argc; ++i){
            if (argv[i] == nullptr) {
                continue;
            }
            string s = argv[i];
            system(("bat in" + s + ".txt " + "ans" + s + ".txt").c_str());
        }
    } else if (op == "-g" || op == "generate") {
        system("cf gen");
    } else {
        puts("Wrong command. Type \"oj -h\" to check. (Without quotation marks)");
    }
    
    return EXIT_SUCCESS;
}

食用方式

注意:本工具内部分功能依赖 cf-tool 请在执行下一步操作前先安装好 cf-tool。
本方法仅仅对 Linux & Unix 用户起效果~请 Windows 用户发扬探索求真的精神,为后人开辟道路 😃

g++ name.cpp -o name -std=c++14
cd /usr/local/bin
ln -s /your/path/to/name name

然后就可以随意使用了~忘记命令时可以打name -h哦。
可能会不定期更新。

Update Logs

upd 2023.8.1

该工具配合 vim 使用更佳哦~

my vimrc:
set autochdir autoread autoindent smartindent cindent udf noerrorbells expandtab
set ts=4 sts=4 sw=4 encoding=utf-8 clipboard=unnamedplus 

set nocompatible
set nobackup
set nowritebackup
set noswapfile

set mouse=a
set shortmess=atI
set backspace=eol,indent,start
syntax enable
syntax on
set nu ru magic hlsearch incsearch
set cursorline cursorcolumn

imap ( ()<esc>i
imap [ []<esc>i
imap { {}<esc>i

nmap <C-a> ggvG$
vmap <C-c> "+y
nmap <C-v> "*p
nmap <F9> :w !oj -t<cr>
nmap <F10> :w !oj -c %<<cr>
nmap <F11>1 :w !oj -v 1<cr>
nmap <F11>2 :w !oj -v 2<cr>
nmap <F11>3 :w !oj -v 3<cr>

autocmd BufNewfile *.cpp 0r ~/Desktop/ckb/template.cpp

upd 2023.9.2

V0.3 支持查看debug的信息

# 使用方法
oj -t -d

等价于

oj -t && cat log.txt

需要在代码中加入文件读写

freopen("log.txt", "w", stderr);

debug时,用 fprintf 或者 cerr 输出

string debug_message = "";
int debug_value = 114514;
fprintf(stderr, "%s:%d", debug_message, debug_value);
// 或者 std::cerr << debug_message << ":" << debug_value;

如果电脑上没安装 bat 的朋友可以安装一下,或者将代码中第 44 行注释,第 45 行取消注释。

# Windows 不清楚
# Mac
brew install bat
# Ubuntu
sudo apt-get install wget
wget https://github.com/sharkdp/bat/releases/tag/v0.18.3/bat_0.18.3_amd64.deb
sudo dpkg -i bat_0.18.3_amd64.deb
老代码(v0.2)存档
#include <bits/stdc++.h>

using namespace std;

int main(int argc, char* argv[]) {
    if (argc < 2) {
        puts("Command needed.");
        return EXIT_FAILURE;
    }

    string op = argv[1];
    if (op == "-h") {
        if (argc < 2) {
            string s = argv[2];
            if (s == "-n" || s == "new") puts("-n name: Create a new problem. (Files inside the dictionary: name.cpp, in1.txt, ans1.txt)");
            if (s == "-a" || s == "add") puts("-a number: Add new samples to the problem. (Files added: in{number}.txt ans{number}.txt))");
            if (s == "-c" || s == "check") puts("-c name: Make stress. (Filename: {name}.cpp {name}_sol.cpp gen.cpp)");
            if (s == "-cls" || s == "clear") puts("-cls name: clear");
            if (s == "-v" || s == "view") puts("-v number: View the sample. (in{number}.txt ans{number}.txt)");
            if (s == "-g" || s == "generate") puts("-g: Generate .cpp file.");
        } else {
            puts("-n(new) name: Create a new problem. (Files inside the dictionary: name.cpp, in1.txt, ans1.txt)");
            puts("-a(add) number: Add new samples to the problem. (Files added: in{number}.txt ans{number}.txt))");
            puts("-c(check) name: Make stress. (Filename: {name}.cpp {name}_sol.cpp gen.cpp)");
            puts("-cls(clear) name: clear");
            puts("-v(view) number: View the sample. (in{number}.txt ans{number}.txt)");
            puts("-g(generate): Generate .cpp file.");
        }
    } else if (op == "-n" || op == "new") {
        for (int i = 2; i <= argc; ++i) {
            if (argv[i] == nullptr) {
                continue;
            }
            string s = argv[i];
            system(("mkdir " + s + " && cd " + s + " && touch in1.txt ans1.txt && cp /your/path/to/template.cpp " + s + ".cpp").c_str());
        }
    } else if (op == "-t" || op == "test") {
        system("cf test");
    } else if (op == "-a" || op == "add") {
        for (int i = 2; i <= argc; ++i) {
            if (argv[i] == nullptr) {
                continue;
            }
            string s = argv[i];
            system(("touch in" + s + ".txt ans" + s + ".txt").c_str());
        }
    } else if (op == "-c" || op == "check") {
        for (int i = 2; i <= argc; ++i){
            if (argv[i] == nullptr) {
                continue;
            }
            string s = argv[i];
            system(("g++-12 " + s + ".cpp " + "-o " + s + " " + "-std=c++14").c_str());
            system(("g++-12 " + s + "_sol.cpp " + "-o " + s + "_ac" + " " + "-std=c++14").c_str());
            system("g++-12 gen.cpp -o gen -std=c++14 -O2 -lm");
            int cnt = 0;
            // puts("Started");
            while (true) {
                system("./gen > in");
                clock_t b = clock();
                system(("./" + s + " < in > sol").c_str());
                clock_t e = clock();
                system(("./" + s + "_ac < in > sol_ac").c_str());
                if (system("diff sol sol_ac -b -B")) {
                    printf("\033[31mWrong Answer\033[m #%d\n", ++cnt); 
                    break;
                } else printf("\033[32mAccepted\033[m #%d ... %dms\n", ++cnt, (e - b) / 12);
            }
        }
    } else if (op == "-cls" || op == "clear") {
        for (int i = 2; i <= argc; ++i){
            if (argv[i] == nullptr) {
                continue;
            }
            string s = argv[i];
            system(("rm " + s + " " + s + "_ac gen in sol sol_ac").c_str());
        }
    } else if (op == "-v" || op == "view") {
        for (int i = 2; i <= argc; ++i){
            if (argv[i] == nullptr) {
                continue;
            }
            string s = argv[i];
            system(("bat in" + s + ".txt " + "ans" + s + ".txt").c_str());
        }
    } else if (op == "-g" || op == "generate") {
        system("cf gen");
    } else {
        puts("Wrong command. Type \"oj -h\" to check. (Without quotation marks)");
    }
    
    return EXIT_SUCCESS;
}

upd 2023.8.20

v0.2 支持多参咯~

# 使用方法
oj -n A B C D

等价于

oj -n A && oj -n B && oj -n C && oj -n D
老代码(v0.1)存档
#include <bits/stdc++.h>

using namespace std;

int main(int argc, char* argv[]) {
    if (argc < 2) {
        puts("Command needed.");
        return EXIT_FAILURE;
    }
    string op = argv[1];
    if (op == "-h") {
        if (argc > 2) {
            string s = argv[2];
            if (s == "-n" || s == "new") puts("-n name: Create a new problem. (Files inside the dictionary: name.cpp, in1.txt, ans1.txt)");
            if (s == "-a" || s == "add") puts("-a number: Add new samples to the problem. (Files added: in{number}.txt ans{number}.txt))");
            if (s == "-c" || s == "check") puts("-c name: Make stress. (Filename: {name}.cpp {name}_sol.cpp gen.cpp)");
            if (s == "-cls" || s == "clear") puts("-cls name: clear");
            if (s == "-v" || s == "view") puts("-v number: View the sample. (in{number}.txt ans{number}.txt)");
            if (s == "-g" || s == "generate") puts("-g: Generate .cpp file.");
        } else {
            puts("-n(new) name: Create a new problem. (Files inside the dictionary: name.cpp, in1.txt, ans1.txt)");
            puts("-a(add) number: Add new samples to the problem. (Files added: in{number}.txt ans{number}.txt))");
            puts("-c(check) name: Make stress. (Filename: {name}.cpp {name}_sol.cpp gen.cpp)");
            puts("-cls(clear) name: clear");
            puts("-v(view) number: View the sample. (in{number}.txt ans{number}.txt)");
            puts("-g(generate): Generate .cpp file.");
        }
    } else if (op == "-n" || op == "new") {
        string s = argv[2];
        system(("mkdir " + s + " && cd " + s + " && touch in1.txt ans1.txt && cp /your/path/to/template.cpp " + s + ".cpp").c_str());
    } else if (op == "-t" || op == "test") {
        system("cf test");
    } else if (op == "-a" || op == "add") {
        string s = argv[2];
        system(("touch in" + s + ".txt ans" + s + ".txt").c_str());
    } else if (op == "-c" || op == "check") {
        string s = argv[2];
        system(("g++-12 " + s + ".cpp " + "-o " + s + " " + "-std=c++14").c_str());
        system(("g++-12 " + s + "_sol.cpp " + "-o " + s + "_ac" + " " + "-std=c++14").c_str());
        system("g++-12 gen.cpp -o gen -std=c++14 -O2 -lm");
        int cnt = 0;
        // puts("Started");
        while (true) {
            system("./gen > in");
            clock_t b = clock();
            system(("./" + s + " < in > sol").c_str());
            clock_t e = clock();
            system(("./" + s + "_ac < in > sol_ac").c_str());
            if (system("diff sol sol_ac -b -B")) {
                printf("\033[31mWrong Answer\033[m #%d\n", ++cnt); 
                break;
            } else printf("\033[32mAccepted\033[m #%d ... %dms\n", ++cnt, (e - b) / 12);
        }
    } else if (op == "-cls" || op == "clear") {
        string s = argv[2];
        system(("rm " + s + " " + s + "_ac gen in sol sol_ac").c_str());
    } else if (op == "-v" || op == "view") {
        string s = argv[2];
        // system(("bat in" + s + ".txt " + "ans" + s + ".txt").c_str());
        system(("cat in" + s + ".txt " + "ans" + s + ".txt").c_str());
    } else if (op == "-g" || op == "generate") {
        system("cf gen");
    } else {
        puts("Wrong command. Type \"oj -h\" to check. (Without quotation marks)");
    }
    
    return EXIT_SUCCESS;
}


  1. cf-tool 原版是由 xalanq 开发的,但是由于codeforces 更新改版,原版 cf-tool 无法正常解析多测样例,所以 woshiluo 大佬就单独提了一个 PR ↩︎