ACM头文件板子
经常有人问我要我的头文件板子于是我就打算来水一篇文章了。
快读快写
因为快读快写是针对某个类型特别设计的,所以如果没有使用对应的读写函数但是依然使用
read和write进行读写的话会产生错误!
普通的scanf和printf打比赛其实已经够了,但是平常为了 装逼 写得方便,因为scanf和printf实在是太长了,就还是用了快读。而且从某种意义上scanf和printf因为太万能了所以也会比快读快写慢那么一丢丢。而且__int128的读入和输出不是也必须要用快读快输么(理直气壮)。
整数
快读
整数快读的原理就是把读数字变成读字符,用getchar读字符非常快。
下面这个是快读板子,支持int, longlong,用的时候就直接read(n);即可,非常方便。
read(n);与scanf("%d", &n);或scanf("%lld", &n);相同作用。不用担心类型不适配,他是个成熟的快读了,会自动适配的。
1 | template <typename T>inline void read(T& x){ |
快写
快写和快读是一个原理,快读是把读数字变成读字符,快写就是把写数字变成写字符,putchar就很快了。
使用的时候直接write(x);即可。
write(x);与printf("%d", x);或scanf("%lld", x);相同作用。不用担心不适配,他是个成熟的快输了,会自动适配的。
1 | template<typename T> inline void write(T x){ |
小数
因为ACM小数一般用的是
double,因此默认小数定义为double,定义float使用小数快读快写可能会出错。
但是问题来了,有整数,小数怎么办?只有整数没有小数这也太不优雅了,而且也没办法摆脱scanf。
快读
小数比整数麻烦一些,因为有整数部分和小数部分,那么就分成两部分来读,然后拼起来就可以了。
使用时直接read(x);即可。
使用了板子后:read(x);与scanf("%lf", &x);相同作用。
1 | inline void read(double &x){ |
快写
快写比快读麻烦很多,也是把小数分成整数和小数两部分,整数部分直接用整数快写就行,小数部分自己动手丰衣足食。另外还要考虑保留几位小数和四舍五入的问题。
下面这个是我参照其他大佬写的然后自己改改实现的小数快写。默认是保留六位小数,四舍五入。
使用时如果默认是保留六位小数那么直接write(x);即可。如果需要保留特殊小数位数,需要多一个参数write(x, k);,k为保留位数。
使用了板子后:write(x);与printf("%lf", x);相同作用。write(x, k);与printf("%.(k)lf", x);相同作用,注意k为参数。另外保守起见最好最多只保留到小数后16位。
1 | inline void write(double x,int k=6){ |
字符串
整数,小数,再来个字符串就完美起来了,字符串肯定是string香啦,但是string是要配合cin读入的,cin不解绑的话就很慢了,于是字符串快读来了。
快读
使用时直接read(x);readline(x);即可。
使用了板子后:read(x);与cin>>x;相同作用。
1 | inline void read(string& x){ |
这样的话就可以实现字符串的快读了,另外可以注意,如果需要读取一行的话,只需要将第二个while里面的ch!=' '删掉就好。
使用了板子后:readline(x);与cin.getline(x,maxsize);相同作用,有点类似于gets(x);。
1 | inline void readline(string& x){ |
快写
使用板子后:write(x);与cout<<x;作用相同。
1 | inline void write(string x){ |
使用时直接write(x);即可。
多参数
快读
欸嘿,有了快读板子就快了起来了,但是我发现如果要读多个的话就要read(x);read(y);,这太傻逼了,还没有scanf快,如果能直接read(x, y);多好,于是有了下面这个配合read实现多参数读入的。加上了之后用的时候直接read(x, y...);即可。
1 | template <typename T,typename... Args> inline void read(T& t, Args&... args){ |
快写
快写与快读不同,因为不能单纯的快写,中间往往有空格,换行或其他字符。所以需要一个辅助输出字符。
1 | template <typename T> inline void write(const char ch, T x){ |
使用方法也与多参数快读不同,第一个参数为输出之间的字符,然后后面的依次为输出的参数。
例如:
write('\n', a, b, c, ...);与printf("%d\n%d\n%d\n",a, b, c);相同作用。
write(' ', a, b, c, ...);与printf("%d %d %d ", a, b, c);相同作用。注意行末有空格。
因为快写设计原因,也可以实现写了就换行,write('\n', x);,这样就和printf("%d\n", x);相同作用。
值得注意的是小数的特殊位数多参数快写这个不能适用,字符串读取一行的也不能,其他的都可以添加上上面两个后实现多参数快读快写。
快读快写大礼包
1 | //---------------------------------------------------// |
头文件板子
板子
下面是我平常打cf刷题的时候用的板子。
1 |
|
将头文件板子与vscode相融合
板子好了,但是问题又来了,如果每次打比赛都要拿板子去粘贴这就太不优雅了。如果能按两个键板子就自己跳出来那么多舒服。
你已经是个成熟的板子了,该学会自己跳出来了。
vscode有个用户自定义代码,我们或许可以利用这个来实现一键出板子。
首先设置->用户代码片段

然后在弹出来的搜索框里面输入cpp,点击cpp.json

接下来会弹出一个json文件,用下面的代码替换内部代码
1 | { |
然后保存即可安心食用。
接下来只需要在cpp文件里面输入ACM三个字母,然后优雅的按一下Enter或者tab,便可以欣赏周围人的对你传来的惊讶声了。


如何使用头文件板子
首先在与源代码同一目录下创建一个in.txt文件,此处装载的是源文件的输入。
编译运行之后程序会自动在in.txt中读取数据作为输入,然后在默认窗口输出。
输出结果无误后将下面代码中的freopen语句注释掉。即可Ctrl+A Ctrl+C然后粘贴到onlinejudge提交代码。

如何更加优雅的使用头文件板子
可以发现虽然已经很简便,但是在提交代码的时候依然需要注释掉一个语句,不是那么优雅。但是可以通过一些操作。即使不用注释掉这个语句,提交到onlinejudge之后也不运行这个语句,这样就少了一步了,懒人的福音。
首先我们需要知道宏定义代码块
1 |
|
那么我们可以用这个来操作一手。
首先gcc/g++ -D _DEBUG命令会自动生成一个对于_DEBUG的宏定义,而在onlinejudge上跑代码是不会含有这个宏定义的,那么我们能够让本地运行的时候多一句gcc/g++ -D _DEBUG,用#ifdef _DEBUG块把freopen语句框起来,这样就可以在本地运行的时候运行freopen,提交之后onlinejudge不运行了。
值得注意的是VS在调试模式中会自动添加_DEBUG的宏定义,就只需要用#ifdef _DEBUG把freopen框起来就可以了。
首先修改cpp.json,在最下方
1 | "signed main(void){ ", |
增加gcc/g++ -D _DEBUG命令。
此处以vscode做例子,修改.vscode>tasks.json。
在args中最前面添加
1 | "-D _DEBUG",//注意行末的逗号 |
保存。效果如下图所示。

现在就可以在本地运行时运行freopen,提交上去之后不运行freopen了。
