C++ 竞赛入门

index

对拍

1. 背景

做题目的时候,如果这个题目的只有样例通过,或只拿到部分的时候,我们需要一个数据,这个数据可以过标程或暴力但不能过过我们的代码,以此来找到我们代码中错误

2. 基础知识

diff命令的使用

diff命令的是linux自带的命令,它可以比较两个文本文件的不同

首先创建两个文件1.txt,2.txt,内容如下

对比
1
2
3
4
5
1
2
2
4
5

[[ctrl]] + [[alt]] + [[t]],打开termial,输入下面的内容

diff 1.txt 2.txt

那么这个输出格式是什么意思呢

得到结果

3c3
< 3
---
> 2

c表示change,3c3表示1.txt的第3行和2.txt的第3行对比,有改变

具体解释见 diff命令输出格式解读_车子 chezi的博客-CSDN博客_diff 输出

你再尝试一下其它命令

# q -> quiet,安静模式,相同,什么也不输出
diff -q 1.txt 1.txt

# q -> quiet,安静模式,不相同,输出指明不同
diff -q 1.txt 2.txt

# y -> side by slide,并排输出

diff -y 1.txt 2.txt

# 指定宽度为30
diff -W 30 -y 1.txt 2.txt

# 只输出不同的行
diff --suppress-common-lines -y 1.txt 2.txt

终极杀招vimdiff

vimdiff 1.txt 2.txt

vimdiff具有下面的优点

  • 命令简单
  • 显示完美
    • 相同的行会折叠
    • 不相同的行会高亮

3. diff 返回的值

我们知道,我们写的c++代表的main函数都会return一个整数,同样diff命令在运行结束 后也会返回一个值. 那么怎么得到这个值呢?

diff 1.txt 1.txt
echo $?

会输出0,表示diff的两个文件一样


4. diff 命令的与||的拼接

diff -q 1.txt 1.txt || echo "yes"

我们知道 在c++,里||是逻辑或运行符号,那么这里是什么意思呢?

比较反直觉的是bash是如何判断一个程序运行的是否正确,如下

  • 一个命令运行的返回值是0,bash认为是true,这个程序运行正确
  • 一个命令运行的返回值是非0,bash认为是false,这个程序运行不正确

||的运算规则和c++里一样,A || B


试一试下面的命令

# 不会输出yes
true || echo "yes"  

# 会输出yes
false || echo "yes"
  • 如果A是true,不会执行B,因为整体A || B一定是true
  • 如果A是false,会执行B

The right side of && will only be evaluated if the exit status of the left side is zero (i.e. true). || is the opposite: it will evaluate the right side only if the left side exit status is non-zero (i.e. false).

参考: https://unix.stackexchange.com/a/24685

结论 只有diff执行失败时才会执行,echo yes

5. 创建 shell 对拍脚本

可以编写 shell 脚本依次运行数据生成程序、标准程序和待测程序,再用 diff 比较输出。将脚本保存为 dp.sh 后,赋予执行权限:

chmod +x dp.sh
./dp.sh

如果希望在任意目录使用脚本,可以将它放入 PATH 中的个人脚本目录,并为不同的 程序名称设计命令行参数。

6 c++对拍程序

Q:因为我不熟悉bash脚本的编写, ,我比赛时无法记住上面的脚本,怎么办呢?

A:使用如下的c++代码

#include <iostream>
using namespace std;

int main(){
    for(int i=1;i<=1000;++i){
        cout << i << "\n";
        // system 相当于手动执行一条命令
        system("./rand > rand.out");
        system("./my < rand.out > my.out");
        system("./right < rand.out > right.out");
        if( system("diff -q my.out right.out") != 0){
            cout << "error \n";
            return 1;
        }
    }
    cout << "all right\n";

    return 0;
}