C++快读和快写

前言

虽然读入优化好像用处不大,但是还是能够在读入数据规模较大的时候提供较大的优化,比如:

用cin输出2000个100000000

用快输输出2000个100000000

单位都是毫秒。可以直观的发现,用快输的话输出时间优化了很多,那么快读是如何做到这样的呢?

原理

众所周知,在c++中,用putchar和getchar输入输出字符的速度是很快的,因此,我们可以考虑把数字转化为字符,按位输出;把字符读入后转化为数字的每一位。

快读

普通快读:

可以读入任意整数类型的变量

template<typename T>inline void readT(T &x){
    bool f=1;x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=!f;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=(f?x:-x);return;
}
读入__int128:

__int128只能用快读读入

inline void read128(__int128 &x){
    bool f=1;x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=!f;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=(f?x:-x);return;
}
超级快读:

经实测,只能读入整数

char buf[1<<20],*p1,*p2;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin), p1 == p2) ? 0 : *p1++)
template<typename T>inline void readT(T &x){
    bool f=1;x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=!f;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=(f?x:-x);return;
}
inline void read128(__int128 &x){
    bool f=1;x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=!f;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=(f?x:-x);return;
}
读入字符串(string类型,不能读入空格)

循环读入每一位就可以了

inline void readS(std::string &s){
	char ch=getchar();
	while(ch==' '||ch=='\n') ch=getchar();
	while(ch!=' '&&ch!='\n') s+=ch,ch=getchar();
}
读入字符串(string类型,读入一行)

同上,循环读入每一位,不过判断的时候把空格保留就可以了

inline void readSL(std::string &s){
	char ch=getchar();
	while(ch=='\n') ch=getchar();
	while(ch!='\n') s+=ch,ch=getchar();
}
读入字符串(char数组型,不能读入空格)

原理同string

inline int readC(char s[]){
	int tot=0;char ch=getchar();
	while(ch==' '||ch=='\n') ch=getchar();
	while(ch!=' '&&ch!='\n') s[tot++]=ch,ch=getchar();
	return tot;
}
读入单个字符(不读入空格和换行)
inline void readc(char &c){
	c=getchar();
	while(c==' '||c=='\n')
		c=getchar();
}

因为受精度的影响,快读读入double的时候会出现比较大的误差,所以推荐使用scanf

快输

普通快输

可以输出常规的整数类型

template<typename T>
inline void writeT(T x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) writeT(x/10);
    putchar(x%10+'0');return;
}
输出__int128
inline void read128(__int128 &x){
    bool f=1;x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=!f;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=(f?x:-x);return;
}
输出字符串
inline void writeS(std::string s){
	int len=s.length();
	for(int i=0;i<len;i++)
		putchar(s[i]);
}

输出单个字符直接用putchar就可以了,同样,输出高精度数直接使用printf吧

读入、输出多个

读入多个

使用template的可变展开

template<typename T>inline void read(T& x) {
	x = 0; bool f = false; char ch = getchar();
	while (ch < '0' || ch>'9') { if (ch == '-') f = !f; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); }
	x = (f ? -x : x); return;
}
template<typename T,typename... Args>
inline void read(T& x,Args&...x_){read(x),read(x_...);}
输出多个

同理

template<typename T>inline void put(T x) {
	if (x < 0) putchar('-'), x = -x;
	if (x > 9) put(x / 10);
	putchar(x % 10 + '0'); return;
}template<typename T>inline void write(T x) {put(x);}
template<typename T,typename... Args>
inline void write(T x,Args...x_){write(x),write(x_...);}

能够支持几乎所有类型的快读快写模板

使用命名空间,使用的时候注意变量名的重复,因为string无法直接比较,所以存在了变量里,使用的时候直接调用write和read函数就可以了,但是字符串的话需要put函数和readS函数

#include<bits/stdc++.h>
namespace Std{
	//不能读入char 
//	char buf[1<<20],*p1,*p2;
//	#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin), p1 == p2) ? 0 : *p1++)
	inline void read128(__int128 &x){
	    bool f=1;x=0;char ch=getchar();
	    while(ch<'0'||ch>'9'){if(ch=='-') f=!f;ch=getchar();}
	    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	    x=(f?x:-x);return;
	}
    inline void write128(__int128 x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) write128(x/10);
        putchar(x%10+'0');return;
    }
    
	inline void readD(double &x){scanf("%lf",&x);}
	
	inline void writeD(double x){printf("%lf",x);}
	
	inline void writeD(double x,int len){printf("%.*lf",len,x);}
	
	template<typename T>inline void readT(T &x){
	    bool f=1;x=0;char ch=getchar();
	    while(ch<'0'||ch>'9'){if(ch=='-') f=!f;ch=getchar();}
	    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	    x=(f?x:-x);return;
	}
	template<typename T>
	inline void writeT(T x){
	    if(x<0) putchar('-'),x=-x;
	    if(x>9) writeT(x/10);
	    putchar(x%10+'0');return;
	}
    
	inline void readS(std::string &s){
		char ch=getchar();
		while(ch==' '||ch=='\n') ch=getchar();
		while(ch!=' '&&ch!='\n') s+=ch,ch=getchar();
	}
	
	inline void readSL(std::string &s){
		char ch=getchar();
		while(ch=='\n') ch=getchar();
		while(ch!='\n') s+=ch,ch=getchar();
	}
	
	inline void writeS(std::string s){
		int len=s.length();
		for(int i=0;i<len;i++)
			putchar(s[i]);
	}
	
	inline int readC(char s[]){
		int tot=0;char ch=getchar();
		while(ch==' '||ch=='\n') ch=getchar();
		while(ch!=' '&&ch!='\n') s[tot++]=ch,ch=getchar();
		return tot;
	}
	inline void writeC(char s[],int len){
		for(int i=0;i<len;i++)
			putchar(s[i]);
	}
	
	inline void readc(char &c){
		c=getchar();
		while(c==' '||c=='\n')
			c=getchar();
	}inline void writec(char c){putchar(c);}
	
	const std::string c="c";
	const std::string i="i";
	const std::string j="j";
	const std::string X="x";
	const std::string y="y";
	const std::string b="b";
	const std::string s="s";
	const std::string Ss="Ss";
	
	template<class T>
	inline void read(T &x) {
		if(typeid(x).name()==i) readT(x);
		else if(typeid(x).name()==j) readT(x);
		else if(typeid(x).name()==X) readT(x);
		else if(typeid(x).name()==y) readT(x);
		if(typeid(x).name()==b){
			int k;readT(k);
			x=(k>0?true:false);
		}else if(typeid(x).name()==s) readT(x);
		else if(typeid(x).name()==c){char ch;readc(ch);x=ch;}
	}
	template<class T,class... Ts>
	inline void read(T &x,Ts&... xx){
		if(typeid(x).name()==i) readT(x);
		else if(typeid(x).name()==j) readT(x);
		else if(typeid(x).name()==X) readT(x);
		else if(typeid(x).name()==y) readT(x);
		if(typeid(x).name()==b){
			int k;readT(k);
			x=(k>0?true:false);
		}else if(typeid(x).name()==s) readT(x);
		else if(typeid(x).name()==c){char ch;readc(ch);x=ch;}
		read(xx...);
	}
	inline void read(std::string &x){readS(x);}
	
	inline void read(char x[]){readC(x);}
	
	inline void read(double &x){readD(x);}
	
	inline void write(double x){writeD(x);}
	
	inline void write(double x,int len){writeD(x,len);}
	
	inline void write(std::string x){writeS(x);}
	
	inline void write(char x[]){writeC(x,strlen(x));}
	
	inline void write(double x,char a){writeD(x);putchar(a);}
	
	inline void write(std::string x,char a){writeS(x);putchar(a);}
	
	inline void write(char x[],char a){writeC(x,strlen(x));putchar(a);}
	
	inline void write(double x,int len,char a){writeD(x,len);putchar(a);}
	
	template<class T>inline void write(T x,char a){
		if(typeid(x).name()==i) writeT(x);
		else if(typeid(x).name()==j) writeT(x);
		else if(typeid(x).name()==X) writeT(x);
		else if(typeid(x).name()==y) writeT(x);
		if(typeid(x).name()==b){
			if(x) writeT(1);
			else writeT(0);
		}else if(typeid(x).name()==s) writeT(x);
		else if(typeid(x).name()==c){writec(x);}
		putchar(a);
	}	
	inline void write(double x,std::string a){writeD(x);writeS(a);}
	
	inline void write(std::string x,std::string a){writeS(x);writeS(a);}
	
	inline void write(char x[],std::string a){writeC(x,strlen(x));writeS(a);}
	
	inline void write(double x,int len,std::string a){writeD(x,len);writeS(a);}
	
	inline void write(char a,std::string s){writec(a);writeS(s);}
	
	template<typename T>inline void write(T x,std::string a){
		if(typeid(x).name()==i) writeT(x);
		else if(typeid(x).name()==j) writeT(x);
		else if(typeid(x).name()==X) writeT(x);
		else if(typeid(x).name()==y) writeT(x);
		if(typeid(x).name()==b){
			if(x) writeT(1);
			else writeT(0);
		}else if(typeid(x).name()==s) writeT(x);
		else if(typeid(x).name()==c){writec(x);}
		writeS(a);
	}
	template<typename T>inline void write(T x){
		if(typeid(x).name()==i) writeT(x);
		else if(typeid(x).name()==j) writeT(x);
		else if(typeid(x).name()==X) writeT(x);
		else if(typeid(x).name()==y) writeT(x);
		if(typeid(x).name()==b){
			if(x) writeT(1);
			else writeT(0);
		}else if(typeid(x).name()==s) writeT(x);
		else if(typeid(x).name()==c) writec(x);
	}
	template<typename T,typename... Ts>
	inline void write(T x,Ts... xx){
		if(typeid(x).name()==i) writeT(x);
		else if(typeid(x).name()==j) writeT(x);
		else if(typeid(x).name()==X) writeT(x);
		else if(typeid(x).name()==y) writeT(x);
		if(typeid(x).name()==b){
			if(x) writeT(1);
			else writeT(0);
		}else if(typeid(x).name()==s) writeT(x);
		else if(typeid(x).name()==c){writec(x);}
		write(xx...);
	}
	inline void put(std::string s){
		int len=s.length();
		for(int i=0;i<len;i++){
			putchar(s[i]);
		}
	}
}
using namespace Std;
using namespace std;

signed main(){
	
}

如果觉得有 帮助的话,给个免费的赞吧😀😀

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
扎眼的阳光的头像扎眼的阳光普通用户
上一篇 2023年12月22日
下一篇 2023年12月22日

相关推荐