C++整数快速读写模板(快速读⼊+快速写)详解众所周知,C++的cin和cout速度很慢,在OJ上会耽误⼤量的时间
因此⼀般使⽤cin,cout时 会在main的第⼀⾏加上⼀句:
iostream::sync_with_stdio(false);
这句话会解除cin,cout和stdio之间的同步锁 这样cin和cout的速度会有明显的改善
和scanf和printf不相上下 有时候甚⾄⽐后两者更快⼀些
但是注意 执⾏完上述语句后只能使⽤{cin,cout}和{printf,scanf,putchar,getchar}的⼀边
如果两个集合⾥的函数混⽤ 会导致输出顺序混乱(前⾯的和后⾯的字符穿插在⼀起乱七⼋糟)
我⼀般习惯解除同步锁之后直接⽤cin,cout
选择上⾯的⽅法或者直接采⽤scanf printf 基本上可以应付绝⼤多数问题 但如果⼀道题⽬的数据量特别⼤
(⽐如T<10000000组输⼊数据 每组若⼲个数的时候) 以上⽅法也有些⼒不从⼼
这时就需要⽤到快速读⼊模板
这个模板的原理之⼀是⽤较快的getchar代替scanf或者cin 使速度有⼀个较⼤的提升
⽽⼀个⼀个字符地getchar显然效率上有些低 所以更好的⽅法是⽤fread把数据读⼊缓冲区(⼀次数万个字符)再处理
这样⼏乎是最快的⽅法了
⽹上有⼀个很流⾏的快读模板(因为到处都是实在不到发布源了)是这样的:
这个也是我们学校学长推荐的快读模板
namespace fastIO {
#define BUF_SIZE 100000
//fread -> read
bool IOerror = 0;
inline char nc() {
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if(p1 == pend) {
p1 = buf;
pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if(pend == p1) {
IOerror = 1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch) {
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
inline void read(int &x) {
char ch;
while(blank(ch = nc()));
if(IOerror)
return;
for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
}
inline void readll(long long int &x) {
char ch;
while(blank(ch = nc()));
if(IOerror)
return;
for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
}
#undef BUF_SIZE
};
上⾯模板的效率确实很⾼ 但是个⼈认为⽤函数来写读⼊很⿇烦
⽐如输⼊三个整数a b c 必须要写read(a);read(b);read(c);才⾏ ⽽且上述模板不⽀持输⼊负数也很⿇烦于是我做了⼀些修改 所有的读⼊函数使⽤重载运算符>>的⽅式实现
⽽且 不限制读⼊的数据类型(如果不是可以加速的整数类型会⾃动转给cin读⼊)
并且增加了⼀个快速写模板 把整数的输出任务⽤putchar执⾏ 也提⾼了输出的速度
修改后的模板如下:(main函数中是测试代码)
#include <bits/stdc++.h>
using namespace std;
// *Copyright by i.Pear Works*
//本IO模块的⽤途是⽅便地读写⼤量整数
//若题⽬整数不多请改⽤关闭同步锁的cin(因为本模块不⽀持关闭同步锁)或scanf
namespace FastIO{
//不⽀持while(qin>>x)的多组数据输⼊⽅法
//任何情况下请不要关闭sync_with_stdio同步锁!!
//如果您选择关闭同步锁以获得更⾼的cin/cout速度使⽤此模块会导致不可预期的后果
//此处为负数读取功能开关
/
/若程序不会读⼊负数请去除下⽅注释符号以获得30%的输⼊提速
//#define DisableNegative true
//#define DisableNegative true
//此处为兼容性模式开关若程序IO存在 *任何* *int/ll/char[]/string/char(包括空格回车)* 之外的类型//请去除下⽅注释符号降低⼀半的速度以获得兼容性
//#define EnableCompatibility true
class Scanner{
char cht;
bool ifNegative;
char stringBuf[10000];
#ifndef EnableCompatibility
#define BUF_SIZE 524288
char nc(){
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if(p1==pend){
p1=buf;
pend=buf+fread(buf,1,BUF_SIZE,stdin);
if(pend==p1)return ' ';
}
#ifndef DisableNegative
if(*p1=='-'){
ifNegative=true;
p1++;
return nc();
}
#endif
return *p1++;
putchar函数}
#else
inline char nc(){
return getchar();
}
#endif
inline bool blank(char ch){
return ch=='\r'||ch=='\n'||ch==' '||ch=='\t';
}
public:
Scanner operator>>(int&x){
#ifndef DisableNegative
ifNegative=false;
#endif
while(blank(cht=nc()));
for(x=cht-'0';(cht=nc())>='0'&&cht<='9';x=x*10+cht-'0');
#ifndef DisableNegative
if(ifNegative)x*=-1;
#endif
return *this;
}
Scanner operator>>(long long int&x){
#ifndef DisableNegative
ifNegative=false;
#endif
while(blank(cht=nc()));
linux书籍pdf下载for(x=cht-'0';(cht=nc())>='0'&&cht<='9';x=x*10+cht-'0');
#ifndef DisableNegative
if(ifNegative)x*=-1;
#endif
return *this;
}
Scanner operator>>(string&str){
int p=0;
while(blank(cht=nc()));
for(stringBuf[p++]=cht;!blank(cht=nc());stringBuf[p++]=cht);
stringBuf[p]='\0';
str=stringBuf;c语言fwrite函数写入失败
return *this;
return *this;
}
Scanner operator>>(char str[]){
int p=0;
while(blank(cht=nc()));
for(str[p++]=cht;!blank(cht=nc());str[p++]=cht);
str[p]='\0';
return *this;
}
ubuntu开启ssh远程登录template<typename F>
inline Scanner operator>>(F&f){
cin>>f;
return *this;
}
};
class Printer{
int num;
char chr[21];
public:
Printer operator<<(int x){
if(x==0){
putchar('0');
return *this;
}
if(x<0)x*=-1,putchar('-');
num=0;
while(x) chr[++num]=(x%10)+48,x/=10;
while(num) putchar(chr[num--]);
return *this;
}
Printer operator<<(long long int x){
if(x==0){
putchar('0');
return *this;
}
if(x<0)x*=-1,putchar('-');
num=0;
while(x) chr[++num]=(x%10)+48,x/=10;
while(num) putchar(chr[num--]);
return *this;
}
inline Printer operator<<(char x){
putchar(x);
return *this;
}
Printer operator<<(const char str[]){
int p=0;
while(str[p]!='\0'){mid函数前面加入汉字
putchar(str[p++]);
}
return *this;
internal名词}
inline Printer operator<<(string&x){
for(string::iterator i=x.begin();i&d();i++)putchar(*i); return *this;
}
template<typename F>
inline Printer operator<<(F&f){
cout<<f;
return *this;
}
};
Scanner qin;
Printer qout;
#define endl '\n'
#define endl '\n'
}
using namespace FastIO;
/
/-----------------模板到此结束以下是测试代码--------------------
int main(){
//test
freopen("D:\\1.txt","r",stdin);
long long int arr[10];
for(int i=1;i<10;i++){
qin>>arr[i];
}
for(int i=1;i<10;i++){
qout<<arr[i]<<endl;
}
}
int main2(){
// !!run this test with "EnableCompatibility" mode on
freopen("D:\\1.txt","r",stdin);
long long int a;
long long int b;
int c;
double d;
string e;
float f;
qin>>a>>b>>c>>d>>e>>f;
qout<<a<<" "<<b<<endl<<c<<" "<<d<<endl<<e<<" "<<f;
}
上⾯的“兼容性模式”是不再建⽴缓冲区⽽⽤疯狂getchar替代 这样不会把后⾯不是整数的数据也存进缓冲区
实验证明这样速度会慢⼀半 但是也⽐scanf快得多
如果不需要读取负数 可以打开上⾯DisableNegative的开关 编译时会少⼏个判断 效率也有⼀些提升
在不开启兼容性+DisableNegative的模式下 和原模板的速度没有区别
简述⼀下⽤法:只要把这段代码粘贴到您代码的最上⽅ 然后使⽤qin,qout(q是quick的意思)代替cin,cout就可以了所有的输⼊输出都使⽤运算符<<,>>来进⾏
经过测速 虽然⽤了⼤量的反复重载和类 速度并未改变 但从使⽤上来说也许会更⽅便⼀些
已知的⼀些问题:
1.qout不能正确的输出-9223372036854775808这个数(ll的最⼩值)因为去掉符号会溢出
但只有这⼀个数不能⽤ 实际需要输出这个数的场合也不多见 就不为了它降低整体效率了
2.快速写部分对于绝⼤多数类型都有加速作⽤ 但是快读只对整数类型起作⽤
如果数据中不是含有⼤量的整数 请慎⽤此模板(因为与sync_with_stdio不共存)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论