C++输入、输出优化模板整理

来源:互联网 发布:淘宝店铺搜索排名 编辑:程序博客网 时间:2024/05/21 07:00

前言

对于在信息学竞赛中逐渐深入学习的C++选手们,会发现有些题目的输入输出量特别大,有时可能一道题读入完你就TLE了。那么怎么办呢?少用cin或者cout,因为如果你对cin或者cout没有进行一些优化的话,它会跑的很慢,所以你如果不会输入输出优化的话,那就乖乖用scanf吧,这样会相对快一点。
但是呢,scanf速度还是不够快,那怎么办呢?那就用输入输出优化吧!

前置知识

getchar是读入函数的一种。它从标准输入里读取下一个字符,相当于getc(stdin)。返回类型为int型,为用户输入的ASCII码,出错返回-1
引用自 百度百科·getchar (计算机语言函数)

看了度娘上的定义,你大概知道getchar()这个函数的定义了吧。然后呢,度娘里没说,这个getchar()还是很快的呢,与它对应的还有一个putchar(),于是呢我们就可以用它来进行输入输出优化啦
(头文件是cstdio)

isdigit是计算机C(C++)语言中的一个函数,主要用于检查参数是否为十进制数字字符。用于判断字符c是否为数字,当c为数字0~9时,返回非零值,否则返回零。 可以用一个字符数组循环判断每一项是否为数字。

嗯,这个isdigit()能判断一个字符是不是数字,好像很有用呢,那就当一个前置知识吧
(头文件是cctype)

输入输出优化的简单版

void read(int&x)//只能读入非负整数{    char cu=getchar();x=0;//x置0,防止x有初始值    while(!isdigit(cu))cu=getchar();    while(isdigit(cu))x=x*10+cu-'0',cu=getchar();}void read(int&x)//能读入正、负整数和0{    char cu=getchar();x=0;    bool fla=0;//记录这个数是不是负数    while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}    while(isdigit(cu))x=x*10+cu-'0',cu=getchar();    if(fla)x=-x; }//以上2个函数的用法为:对一个整型a,read(a)即可void print(int x)//只能输出非负整数{    if(x>=10)print(x/10);    putchar(x%10+'0');}void print(int x)//能输出正、负整数和0{    if(x<0)x=-x,putchar('\n');    if(x>=10)print(x/10);    putchar(x%10+'0');}//以上2个函数的用法为:对一个整型a,print(a)即可

这样你就会发现,你的输入输出快乐很多,如果算法相同,输入输出量较大,速度优势会比较明显呢。
嗯,好,如果你看懂了上面的代码,那我就贴一波我自己用的代码(加了一波优化,不要问我什么意思,有些关键词如果不知道就自己去查吧)

template <typename T> inline void read(T&x){    char cu=getchar();x=0;bool fla=0;    while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}    while(isdigit(cu))x=x*10+cu-'0',cu=getchar();    if(fla)x=-x; }template <typename T> void printe(const T x){    if(x>=10)printe(x/10);    putchar(x%10+'0');}template <typename T> inline void print(const T x){    if(x<0)putchar('-'),printe(-x);    else printe(x);}

温馨提醒
使用这份输入输出代码时请不要用它来读入小数、字符串之类的(因为这份代码是读整型的啊),还有如果你不得已还要用其它的东西,那请你谨慎使用,因为这份读优可能会吃掉你的下个字符(有可能是换行符)。当然你要是完全理解了,当然可以使用啦

输入输出优化的升级组件

哇~用了读优之后程序读入的飞快呢~对吧。
然后呢,我想告诉你的是,你还是会在输入速度上被碾压,为什么呢?因为还可以继续优化哦
请看getchar()的函数内容

int getchar(void){    static char buf[BUFSIZ];    static char* bb=buf;    static int n=0;    if(n==0)    {        n=read(0,buf,BUFSIZ);        bb=buf;    }    return(--n>=0)?(unsigned char)*bb++:EOF;}

是不是有优化的空间呢,用fread,一次多读一些东西就快了,自己实现,自然会比自带的快呢(C++自带的会因为考虑一些安全问题而变慢)
具体怎么优化呢?看下面

namespace fast_IO{    const int IN_LEN=10000000,OUT_LEN=10000000;    char ibuf[IN_LEN],obuf[OUT_LEN],*ih=ibuf+IN_LEN,*oh=obuf;    char *lastin=ibuf+IN_LEN;    const char *lastout=ibuf+OUT_LEN-1;    inline char getchar_()    {        if(ih==lastin)lastin=ibuf+fread(ibuf,1,IN_LEN,stdin),ih=ibuf;        return (*ih++);    }    inline void putchar_(const char x)    {        if(ih==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf;        *oh++=x;    }    inline void flush(){fwrite(obuf, 1, oh - obuf, stdout);}}using namespace fast_IO;#define getchar() getchar_()#define putchar(x) putchar_((x))int main(){    return flush(),0;//别忘了这个flush哦,放在这里是不会出问题的,要是你没打那可就不能用这个优化了}

前面那一段要放在程序的最前面,然后还要说一件事,#define getchar() getchar_()、#define putchar(x) putchar_((x))最好在你自己调试的时候注释掉,或者你用文件输入输出(freopen),否则你会发现你的程序会一直显示等你输入

总结

在C++中,输入输出有很多优化,这只是一种,但又很有效。不过呢,要用的话最好要自己理解,否则可能会出问题,几个注意事项:

  • namespace fast_IO 那一段要打在最前面
  • read()、print()只能输入输出整数
  • 用read()、print()的时候用其它输入输出方式(cin、cout、gets()、scanf、printf、puts())要谨慎使用,用namespace fast_IO的时候禁止使用其它输入输出方式
  • 使用namespace fast_IO要注意内存问题,那里面有一个很大的char数组,小心MLE
    最后贴出所有输入输出整合在一起的代码
#include<cstdio>#include<cctype>namespace fast_IO{    const int IN_LEN=10000000,OUT_LEN=10000000;    char ibuf[IN_LEN],obuf[OUT_LEN],*ih=ibuf+IN_LEN,*oh=obuf;    char *lastin=ibuf+IN_LEN;    const char *lastout=ibuf+OUT_LEN-1;    inline char getchar_()    {        if(ih==lastin)lastin=ibuf+fread(ibuf,1,IN_LEN,stdin),ih=ibuf;        return (*ih++);    }    inline void putchar_(const char x)    {        if(ih==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf;        *oh++=x;    }    inline void flush(){fwrite(obuf, 1, oh - obuf, stdout);}}using namespace fast_IO;#define getchar() getchar_()#define putchar(x) putchar_((x))template <typename T> inline void read(T&x){    char cu=getchar();x=0;bool fla=0;    while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}    while(isdigit(cu))x=x*10+cu-'0',cu=getchar();    if(fla)x=-x; }template <typename T> void printe(const T x){    if(x>=10)printe(x/10);    putchar(x%10+'0');}template <typename T> inline void print(const T x){    if(x<0)putchar('-'),printe(-x);    else printe(x);}int main(){    return flush(),0;}

大家学一下输入输出优化,能让自己的程序跑的更快哦

原创粉丝点击