【快速读入数据(快读)】

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_41879343/article/details/102701398

为什么要使用快读?

刚学C++时,我喜欢用这种方式来读入数据:

int x;
cin >> x;

这个读入简单方便,但是到后面我们做题的过程中,我们发现cin 虽然读入方式简单方便,但是它的效率却是极低。于是我在网上查找资料有没有方法让cin的速度提高,功夫不负有心人,我开始用下面的方法读入数据:

std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);

int x;
cin >> x;
  • std::ios::sync_with_stdio(false);
    在c++中之所以cin效率低,是因为先把要输出的东西存入缓冲区,再输出,导致效率降低,而这段语句可以来打消iostream的输入和输出缓存,可节省时间,使效率与scanf与printf相差无几,还有应注意的是scanf与printf使用的头文件应是stdio.h而不是 iostream。
  • tie 函数
    tie是将两个stream绑定的函数,空参数的话返回当前的输出流指针。
    在ACM里,经常出现 数据集超大造成 cin TLE的情况。我们可以在IO之前将stdio解除绑定,这样做了之后要注意不要同时混用cout和printf 之类。
    在默认的情况下cin绑定的是cout,每次执行 << 操作符的时候都要调用flush,这样会增加IO负担。可以通过tie(0)(0表示NULL)来解除cin与cout的绑定,进一步加快执行效率。

用上这一条语句后就不能再用scanf和printf了

再后来,有部分题的输入太多,关闭同步(解除绑定)的cin与scanf的差距就体现出来了,scanf能过的题,cin还是不一定能过。

于是后面我就经常使用scanf。
这样虽然快了,能通过大部分题了。
但是有一些题还是会卡,于是我就接触到了快读这个方式。

快读的思路

因为getchar()比scanf要快,故为了加快读入,可以用getchar()代替scanf.
利用getchar()将数字读入,若为” “或”\n”结束,第一个字符判断一下数字的正负,然后每读入一个数字就将当前数*10并加上它,最终做为函数返回值返回。

快读的代码

int read()
{
	char ch=getchar();int x=0,f=1;
	while(ch<'0' || ch>'9')	{if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}

快读模板代码优化

#define re register
inline int read()
{
    re int x=0,f=1;
    re char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}

在早期c语言编译器不会对代码进行优化,因此使用register关键字修饰变量是很好的补充,大大提高的速度。

register关键字请求让编译器将变量a直接放入寄存器里面,以提高读取速度,在C语言中register关键字修饰的变量不可以被取地址,但是c++中进行了优化。

c++中依然支持register关键字,但是c++编译器也有自己的优化方式,即某些变量不用register关键字进行修饰,编译器也会将多次连续使用的变量优化放入寄存器中,例如入for循环的循环变量i。

c++中也可以对register修饰的变量取地址,不过c++编译器发现程序中需要取register关键字修饰的变量的地址时,register关键字的声明将变得无效。

猜你喜欢

转载自blog.csdn.net/qq_41879343/article/details/102701398
今日推荐