快读快写和fread,fwrite--zhengjun
首先,先谈谈快读快写
这是我一开始的输入输出
cin>>a;
cout<<a;
然后,因为在一次模拟赛中\(cin\)被卡掉了,于是,我就改用
scanf("%d",&a);
printf("%d",a);
可是,又有一道题,我打出了正解,可是\(T\)掉了一个点,结果用了快读快写,就\(A\)了,为什么快读会这么快,因为读入输出字符比读入输出数字快许多
不过,快读还有可能被卡,比如说一个数据,有许多多余的空格,这样你就没办法了,只好改回\(scanf\)。(不过我没有见过这么毒瘤的数据),当然快写也可以用递归式的,不过这样似乎会慢一点
inline void read(register int &x){
x=0;register int f=1;register char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}//判断负数
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
//其中(x<<3)+(x<<1)等价于x*10,(c^48)等价于c-'0'
x*=f;
}
inline void write(register int &x){
register int len=0,k1=x;
if(k1<0)k1=-k1,putchar('-');
while(k1)c[len++]=k1%10+'0',k1/=10;
while(le--)putchar(c[len]);
}
这样,就是一个快读快写了。
当然你也可以写成有返回值的形式,不过我觉得\(void\)会快一点,因为它少定义一个变量
inline int read(){
register int x=0,f=1;register char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}//判断负数
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
//其中(x<<3)+(x<<1)等价于x*10,(c^48)等价于c-'0'
return x*f;
}
inline void write(register int x){
if(x>9)write(x/10);
putchar(x%10+'0');
}
还有一点,快写是输不出\(0\)的,因为我习惯用\(print\),所以,快写用\(write\),再用一个\(define\)
#define print(x) if(x==0)putchar('0');else write(x)
不知道为什么用三目表达式会编译错误。
然后,来说一说fread和fwrite
这个东西是个啥呢,就是文件读入输出的东西,如果不是文件读入的话\(fread\)是不能用的,而\(fwrite\)是可以用的。
这个东西因为我们一次一次分开读入输出一个字符没有通过文件一次性读入输出一坨快,所以,就有了优化。
这两个东西在各种\(OJ\)上面还是适用的,因为\(OJ\)上就是文件读入输出的。
size_t fread( void *restrict buffer, size_t size, size_t count, FILE *restrict stream );
\(buffer\)是读入的数据存放的字符串,\(size\)是每一次读入的个数,\(count\)是读入的次数,\(stream\)是输入流
可是本来可以在\(fread\)里面每一次多读入几次,可是如果剩余的数据不够了,就无法读入成功,而\(stat\)可以求出文件的长度这样就可以了,可是\(windows\)似乎不行,哎!!!
\(fread\)的返回值是
如果读入成功(一定要读完,说要读多少个少一个都不行),返回1,否则返回0
size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
这个其实和\(fread\)的参数一样。只不过我们可以在输出的时候一次全部输出玩,也就是fwrite(buffer,1,buffer的len,stream);
然后,这两个东西就可以替代\(getchar\)和\(putchar\),会快一点。
这里要用到指针,如果不会的请先学习指针,然后再来看。
static char buf[1000000],*p1=buf,*p2=buf,obuf[1000000],*p3=obuf;
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++
#define putchar(x) (p3-obuf<1000000)?(*p3++=x):(fwrite(obuf,p3-obuf,1,stdout),p3=obuf,*p3++=x)
注意\(getchar()\)里面的
(p2=(p1=buf)+fread(buf,1,1000000,stdin)
中的加号是指针。
最终的模板
#include<bits/stdc++.h>
using namespace std;
static char buf[1000000],*p1=buf,*p2=buf,obuf[1000000],*p3=obuf;
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++
#define putchar(x) (p3-obuf<1000000)?(*p3++=x):(fwrite(obuf,p3-obuf,1,stdout),p3=obuf,*p3++=x)
template<typename item>
inline void read(register item &x){
x=0;register int f=1;register char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
x*=f;
}
template<typename item>
inline void uread(register item &x){
x=0;register char c=getchar();
while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
}
static char cc[20];
template<typename item>
inline void print(register item x){
register int len=0;
if(x<0)x=-x,putchar('-');
while(x)cc[len++]=x%10+'0',x/=10;
while(len--)putchar(cc[len]);
}
template<typename item>
inline void uprint(register item x){
register int len=0;
while(x)cc[len++]=x%10+'0',x/=10;
while(len--)putchar(cc[len]);
}
int main(){
fwrite(obuf,p3-obuf,1,stdout);
return 0;
}
普通的输入输出:read(x),print(x)
,无符号的输入:uread()
支持同一文件中的int
和long long
的同时输入输出
例如:
int main(){
int x;
unsigned int ux;
long long y;
unsigned long long uy;
read(x);uread(ux);
read(y);uread(uy);
print(x);putchar(' ');uprint(ux);
putchar('\n');
print(y);putchar(' ');uprint(uy);
fwrite(obuf,p3-obuf,1,stdout);
return 0;
}
输出