天天看点

真正的读写优化NoteUpdates正文

Note

注意,如果您有正确使用freadfwrite的能力,请拆开此模板,使用裸的freadfwrite。本模板为了安全性和完整性包装了许多东西,虽然加了很多常数优化,直接使用freadfwrite还是会更快。
有些人说本模板太长,我在这里做出统一答复:模板长是因为要实现全面的操作和维护使用安全性,只需要记忆getch和putch函数以代替getchar和putchar就行。还嫌长那就先去把getchar和putchar学会吧。
所以要记忆本模板时,比起普通的快速读写只需要多记忆2个函数而已,getch和putch。

本文在github的链接:https://github.com/huanghaox1212/FastIO

Updates

u p d a t e 1 : update1: update1:应某用户建议,已将模板改为 c l a s s class class。

u p d a t e 2 : update2: update2:某用户发现 p u t s puts puts函数运行效率存在问题,已更正。

u p d a t e 3 : update3: update3:应某用户建议,已修改 g o go go函数至析构函数。

u p d a t e 4 : update4: update4:为防止用户使用错误,将 F a s t I O FastIO FastIO的对象的定义置于模板中。

u p d a t e 5 : update5: update5:删去了 r f i l e rfile rfile和 w f i l e wfile wfile。

u p d a t e 6 : update6: update6:应某用户建议,输出 s t r i n g string string的函数参数类型改为了 c o n s t   s t r i n g & const\ string\& const string&。

u p d a t e 7 : update7: update7:经核实发现本模板在效率方面有一些问题,进行了全面修改,并加入_endl和_prs和_setprecision等控制类型。

详情请参照正文。

如果您按照指定方法使用仍然存在bug,请私信我。

正文

黑科技,稳定、高效率且全面+疯狂常数优化的模板。

D e v C p p 5.11 + S a m s u n g   W i n d o w s 7 DevCpp5.11+Samsung\ Windows7 DevCpp5.11+Samsung Windows7环境下评测,(编译后运行)读入并输出1802KB字符,本模板耗时1.27ms, g e t c h a r getchar getchar和 p u t c h a r putchar putchar耗时1524.67ms, c i n c o u t cincout cincout和 s c a n f p r i n t f scanfprintf scanfprintf直接崩溃。

首先模板献上:

(注意:为避免错误使用,使用前一定要查看后面的使用说明)

#include<bits/stdc++.h>
using namespace std;
#define reg register
struct control{
	int ct,val;
	control(int Ct,int Val=-1):ct(Ct),val(Val){}
	inline control operator()(int Val){
		return control(ct,Val);
	}
}_endl(0),_prs(1),_setprecision(2);
struct FastIO{
	#define IOSIZE 1000000
	char in[IOSIZE],*p,*pp,out[IOSIZE],*q,*qq,ch[20],*t,b,K,prs;
	FastIO():p(in),pp(in),q(out),qq(out+IOSIZE),t(ch),b(1),K(6){}
	~FastIO(){fwrite(out,1,q-out,stdout);}
	inline char getch(){
		return p==pp&&(pp=(p=in)+fread(in,1,IOSIZE,stdin),p==pp)?b=0,EOF:*p++;
	}
	inline void putch(char x){
		q==qq&&(fwrite(out,1,q-out,stdout),q=out),*q++=x;
	}
	inline void puts(const char str[]){fwrite(out,1,q-out,stdout),fwrite(str,1,strlen(str),stdout),q=out;}
	inline void getline(string& s){
		s="";
		for(reg char ch;(ch=getch())!='\n'&&b;)s+=ch;
	}
	#define indef(T) inline FastIO& operator>>(T& x){\
		x=0;reg char f=0,ch;\
		while(!isdigit(ch=getch())&&b)f|=ch=='-';\
		while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getch();\
		return x=f?-x:x,*this;\
	}
	indef(int)
	indef(long long)
	inline FastIO& operator>>(char& ch){return ch=getch(),*this;}
	inline FastIO& operator>>(string& s){
		s="";reg char ch;
		while(isspace(ch=getch())&&b);
		while(!isspace(ch)&&b)s+=ch,ch=getch();
		return *this;
	}
	inline FastIO& operator>>(double& x){
		x=0;reg char f=0,ch;
        double d=0.1;
        while(!isdigit(ch=getch())&&b)f|=(ch=='-');
        while(isdigit(ch))x=x*10+(ch^48),ch=getch();
        if(ch=='.')while(isdigit(ch=getch()))x+=d*(ch^48),d*=0.1;
        return x=f?-x:x,*this;
	}
	#define outdef(_T) inline FastIO& operator<<(_T x){\
		!x&&(putch('0'),0),x<0&&(putch('-'),x=-x);\
		while(x)*t++=x%10+48,x/=10;\
		while(t!=ch)*q++=*--t;\
		return *this;\
	}
	outdef(int)
	outdef(long long)
	inline FastIO& operator<<(char ch){return putch(ch),*this;}
	inline FastIO& operator<<(const char str[]){return puts(str),*this;}
	inline FastIO& operator<<(const string& s){return puts(s.c_str()),*this;}
	inline FastIO& operator<<(double x){
		reg int k=0;
		this->operator<<(int(x));
		putch('.');
		x-=int(x);
		prs&&(x+=5*pow(10,-K-1));
		while(k<K)putch(int(x*=10)^48),x-=int(x),++k;
		return *this;
	}
	inline FastIO& operator<<(const control& cl){
		switch(cl.ct){
			case 0:putch('\n');break;
			case 1:prs=cl.val;break;
			case 2:K=cl.val;break;
		}
	}
	inline operator bool(){return b;}
}io;
           

原理:每次批量读入1000001字节,存到输入项里,读完了继续尝试读入,存到输入项里。每次批量输出1000001字节,最后用析构函数把输出项里剩下的也输出了。如果觉得空间会超限(大约2KB的读写数组,超限的可能还是很小的),请自行调整批量读写的数据大小。

使用说明:

1.本模板的文件流没有兼容用其他的任何输入/输出,包括getchar、putchar、cin、scanf之类。一般情况下该模板足以实现常用的读写功能,如果仍然有特殊需求,请自行添加功能。

2.FastIO的定义必须为全局变量。为了防止有人误用,已经加在模板里,请勿多此一举在代码里写出FastIO io的定义。

3.具体用法如下:

· 预处理

#include <bits/stdc++.h>//头文件不要乱改,否则会不支持某些函数。
using namespace std;
//在此处,即using语句的下一句加入模板。
//other defines.
int main(){
    freopen(输入文件名,"r",stdin),freopen(输出文件名,"w",stdout);
    //注意在标准输入输出评测时去掉freopen语句
    //调试时一定要用文件读写,否则输入会卡死(评测机上不会)。
    //由于所有评测机本质上皆使用文件式评测,无需担心会在评测机上出错(亲测通过Luogu和OJ评测)。
    return 0;
}
           

· 输入输出

char ch;int a;long long d;string s1,s2;double aa,bb;
io>>ch>>a>>d>>s1>>aa>>bb,io<<ch<<a<<d<<s1<<aa<<bb;
io.getline(s2),io<<s2,io.puts("123"),io<<"456";
//<<输出操作不能与>>输入操作连在一起!
           

· 判断EOF(使用重载类型转换运算符实现)

while(io>>ch)io<<ch;//判断方法与cin类似。
if(io)...
           

· 控制类型的使用

io<<_endl;//换行
io<<_prs(true);//从现在开始,一律选择进行四舍五入
io<<_prs(false);//从现在开始,一律不进行四舍五入
io<<_setprecision(k);//从现在开始,一律保留k位小数
//注意:控制类型仅为方便习惯于iostream的用户来使用,平时尽量不要用,否则会对效率进行影响。
           

· 其他

//那个模板中,可以把不要的重载运算符删掉,比如只需要输入输出整数,就把输入输出字符串之类的删掉。
//如果需要别的实现,请以getch和putch代替getchar和putchar,然后自行实现。
//以下几个函数/变量千万不能删掉:
//FastIO,~FastIO,getch,putch,in,out,p,pp,q,qq
//有时编译时可能会有警告,不用担心,可放心使用。
//警告原因:
//1.输出C风格字符串的函数参数是const类型,输出字符串变量时会警告。
//2.为了常数优化,部分int换成了char,某些编译器会进行警告。
           
c++

继续阅读