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
了。