C++对拍即调试技巧

一、生成数据

若是生成数据输出文件操作应写成 freopen("something.in","w",stdout);

1. 生成随机序列

int p[N];
for(int i=1;i<=n;i++) p[i]=i;
random_shuffle(p+1,p+n+1);//打乱一个数组
for(int i=1;i<=n;i++) cout<<p[i]<<" ";

这样生成一个 1n 的随机排列

2. 生成随机一棵树

for(int i=2;i<=n;i++)
cout<<rand%(i-1)+1<<" "<<i<<endl;

这样生成一棵以 1 为根的树

3. 生成随机无自环无重边的无向图

//预定n为点数,m为边数
set<pair<int,int> >s;//边的集合
for(int i=1;i<=m;i++)
{
int from=rand%n+1,to=rand%n+1;
if(from==to)//判自环
{
i--;
continue;
}
if(s.count(make_pair(from,to))||s.count(make_pair(to,from)))//判重边,如果是有向图把后面(to,from)的删掉
{
i--;
continue;
}
s.insert(make_pair(from,to));//加入边的集合
cout<<from<<" "<<to<<endl;//输出
}

生成一个 n 个点,m 条边,无自环无重边的无向图


二、对拍程序怎么写

我们令数据生成器、自己猜想的正解与暴力放在同一个根目录下

令数据生成器可执行文件的文件名名为 produce,自己猜想的正解可执行文件名为a,暴力可执行文件名为ba 的输出文件为 A.outb 的输出文件为 B.out (Linux下可执行文件文件名没有后缀,Windows下为.exe

对拍程序 check.cpp 写法如下:(要对拍直接运行 check 即可,默认在Linux下运行

#include<bits/stdc++.h>
using namespace std;
int main()
{
int cnt=0;//统计对的个数
while(true)
{
system("./produce");
system("./a");
system("./b");//运行produce,a,b三个程序
if(system("diff A.out B.out"))//比较A.out与B.out,如果不一样会返回1(Linux下)
{
puts("WA");
return 0;
}
else printf("AC %d\n",++cnt);//对的个数加1
}
return 0;
}
//另外,想要停止要按 Ctrl + Z

数据生成器除了用来生成数据进行对拍外,还可以用来测试时间复杂度是否正确。生成一组极限数据, 然后在 Linux 下使用命令 time 来测试程序运行的时间

比如假设正解名称还是上文中的 a.cpp,那可以在控制台输入命令:

time ./a

返回时会由上到下返回三个时间:real,user,sys

其中 user 是程序将要评测机上运行的时间,如果 user 所指的时间大于题面要求时限,说明程序 百分百TLE


三、调试

1. 输出中间变量调试

输出变量以调试,直到找到出错的部分

建议输出加一些提示的信息

这就不详细讲了吧……?

2. 单步调试 GDB

这个默认在 Windows 下调试,而且所涉及的 路径名文件名不可以有空格

首先得找到并编译文件,按 Win + R 在里面输入 cmd

先切换到文件所在的硬盘,在终端里输入 硬盘 :,比如D盘输入 D:

然后再复制要编译调试的文件所在的文件夹的位置,在终端里输入 cd 路径名,比如输入 D:\vscode_code

再编译文件。编译格式:g++ -g -o 生成可执行文件名.exe 要编译的文件名.cpp(本文默认 C++PythonC等也行)

然后如果想运行的话,直接输入可执行文件名.exe 即可

若想调试则输入 gdb 可执行文件名.exe

不懂的可以看这张图,说的就是上面的步骤:(图中的 Temp_the_test.cpp洛谷P1850换教室AC 代码)

GDB调试示意图

找到并编辑文件后,我们就可以进入调试时间了!

首先开始调试文件,格式上面已经说过了。

按下回车以后会有很多英文蹦出来,不用担心,这些都是在讲 GDB 版权(

调试需要记住一些调试指令:

全称 简写 作用
list l 显示当前程序停止的位置附近的源代码(我试过,我的电脑上最多显示 10 行)
run r 从头开始运行程序,直到断点处为止(没有断点的话直接运行完)
break b 设置断点,后面跟行号,也可以跟函数名(在这个函数这个参数的状态时停止)、if 语句(当……时停止)
next n 执行下一条语句,但不进入函数
step s 执行下一条语句,如果有函数则执行函数内语句
print p 在运行到当前行数时显示一个变量或数组的值
display disp 永久显示一个变量或数组的值,直到程序结束
clear cl 清除某一行的断点,如果什么都不跟则是清除所有断点
undisplay undis 后面跟变量的编号(之前显示的 $1 等,只需要输入序号,不需要输入 $),可以不再显示某个变量的值
watch wa 后面跟变量名,可以在变量发生变化时停止程序运行并输出变化前后的值
continue c 在程序当前停止的为止继续运行,直到运行到下一个断点处
until u 从当前位置开始,执行到 until 要求的行号或者函数名或者 if 条件(不懂得可以看 break 语句)
Enter(回车) 寻找从输入该回车上方最近的一条明确指示了的语句,执行它

四、总结

预祝各位NOIPRP++

posted @   DreamerX  阅读(378)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示