输入输出优化集锦

Update:
2020.02.18 退役了还来更新。加了一个counter。在第六大块添加了一些。在第五大块加了一个print2
2020.3.31 发现了两个神奇的东西,fputs和fgets。

目前在大改中

404

$ $

这里主要针对输入。
$ $
$ $

1.最快的,比大多数getchar党快不少:

P.S.可以筛掉空格、回车、Tab

inline int read()
{
    register char ch=getchar();
    register int x=0;
    while(!(ch&16))ch=getchar();
    while(ch&16)x=(x<<1)+(x<<3)+ch-48,ch=getchar();
    return x;
}
inline int sread()
{
    register char ch=getchar();
    register int x=0;
    register bool b=0;
    while(!(ch&16)&&ch!='-')ch=getchar();
    (ch=='-')&&(b=1,ch=getchar());
    while(ch&16)x=(x<<1)+(x<<3)+ch-48,ch=getchar();
    b&&(x=-x);
    return x;
}

fread?不存在的。我太水了。
有人曾指出应先减48再加ch,其实先加再减即使爆int了也没事的。(想一想,为什么)

$ $

2.略慢一点的:

可以筛掉空格、回车、Tab和大小写字母

inline int read()
{
    register char ch=getchar();
    register int x=0;
    while(!(ch&16)&&(ch&64))ch=getchar();
    while((ch&16)&&!(ch&64))x=(x<<1)+(x<<3)+ch-48,ch=getchar();
    return x;
}
inline int signed_read()
{
    register char ch=getchar();
    register int x=0;
    register bool b=0;
    while(!(ch&16)&&(ch&64)&&ch!='-')ch=getchar();
    (ch=='-')&&(b=1,ch=getchar());
    while((ch&16)&&!(ch&64))x=(x<<1)+(x<<3)+ch-48,ch=getchar();
    b&&(x=-x);
    return x;
}

$ $

3.最常用的,顺便把print()放到这儿:

inline int read()
{
    register char ch=getchar();
    register int x=0;
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar();
    return x;
}
inline int signed_read()
{
    register char ch=getchar();
    register int x=0;
    register bool b=0;
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    (ch=='-')&&(b=1,ch=getchar());
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar();
    b&&(x=-x);
    return x;
}
#include<limits.h>//别忘了
inline void print(int x)
{
    if(!x){putchar('0');return;}
    register short cnt=0;//有位大神(没记错是cz)说过,一般电脑short寄存器很少,所以常常reigster short比register int还慢。确实是的。
    char ch[11];
    (x&INT_MIN)&&(putchar('-'),x=-x);
    while(x)ch[cnt++]=x%10+48,x/=10;
    while(cnt--)putchar(ch[cnt]);
}
inline void unsigned_print(int x)//参数可以改成unsigned修饰的类型,但一般为了和程序主体兼容还是用带符号的。下同。
{
    if(!x){putchar('0');return;}
    register short cnt=0;
    char ch[11];
    while(x)ch[cnt++]=x%10+48,x/=10;
    while(cnt--)putchar(ch[cnt]);
}

$ $

4.不需要limits.h的:

inline void print(int x)
{
    if(!x){putchar('0');return;}
    register short cnt=0;
    char ch[11];
    (x&2147483648u)&&(putchar('-'),x=-x);
    while(x)ch[cnt++]=x%10+48,x/=10;
    while(cnt--)putchar(ch[cnt]);
}

$ $

$\mathtt{\color{#cc0505}\text{注意以上所有内容都会在输出-2147483648时爆炸}}$

5.最稳定不会炸的版本:

inline void putstr(const char *ch)//注意没有const会警告  不要忘了这个函数,不然十年OI一场空!
{
    while(*ch)putchar(*(ch++));
}
inline void print(int x)
{
    if(!x){putchar('0');return;}
    if(x==2147483648u){putstr("-2147483648");return;}
    register short cnt=0;
    char ch[11];
    (x&2147483648u)&&(putchar('-'),x=-x);
    while(x)ch[cnt++]=x%10+48,x/=10;
    while(cnt--)putchar(ch[cnt]);
}
inline void unsigned_print(int x)
{
    if(!x){putchar('0');return;}
    register short cnt=0;
    char ch[11];
    while(x)ch[cnt++]=x%10+48,x/=10;
    while(cnt--)putchar(ch[cnt]);
}

$ $
还有一个print2,用累乘法跟print效率不相上下(在洛谷IDE和某些OJ上print2快,在自家i3古董上print快一些)

inline void print2(int x)
{
    if(!x){putchar('0');return;}
    if(x==2147483648u){printf("-2147483648");return;}
    (x&2147483648u)&&(putchar('-'),x=-x);
    if(x==1000000000){printf("1000000000");return;}//防止在1e9时出锅
    (x>1000000000)&&(putchar(x/1000000000+48),x%=1000000000);//防止在1e9以上时出锅
    register int cnt=1;
    while(cnt<=x)cnt*=10;
    while(cnt/=10)putchar(x/cnt+48),x%=cnt;
}
inline void unsigned_print2(int x)
{
    if(!x){putchar('0');return;}
    if(x==1000000000){printf("1000000000");return;}
    (x>1000000000)&&(putchar(x/1000000000+48),x%=1000000000);
    register int cnt=1;
    while(cnt<=x)cnt*=10;
    while(cnt/=10)putchar(x/cnt+48),x%=cnt;
}

$ $
$ $

6.其他乱七八糟的:

inline long long readll()
{
    register char ch=getchar();
    register long long x=0;
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-48,ch=getchar();
    return x;
}
inline long long signed_readll()
{
    register char ch=getchar();
    register bool b=true;
    register long long x=0;
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    (ch=='-')&&(b=1,ch=getchar());
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar();
    b&&(x=-x);
    return x;
}
inline void print(long long x)
{
    if(!x){putchar('0');return;}
    register short cnt=0;
    char ch[21];
//  (x&-9223372036854775808ll)&&(putchar('-'),x=-x);这个注释是干什么的我就不说了
    (x&LONG_LONG_MIN)&&(putchar('-'),x=-x);
    while(x)ch[cnt++]=x%10+48,x/=10;
    while(cnt--)putchar(ch[cnt]);
}
inline void unsigned_print(long long x)
{
    if(!x){putchar('0');return;}
    register short cnt=0;
    char ch[21];
    while(x)ch[cnt++]=x%10+48,x/=10;
    while(cnt--)putchar(ch[cnt]);
}
inline __int128 read128()
{
    register char ch=getchar();
    register __int128 x=0;
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-48,ch=getchar();
    return x;
}
inline __int128 signed_read128()
{
    register char ch=getchar();
    register bool b=true;
    register __int128 x=0;
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    (ch=='-')&&(b=1,ch=getchar());
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-48,ch=getchar();
    b&&(x=-x);
    return x;
}
inline void print(__int128 x)
{
    if(!x){putchar('0');return;}
    register short cnt=0;
    char ch[42];
    (x<0)&&(putchar('-'),x=-x);
    while(x)ch[cnt++]=x%10+48,x/=10;
    while(cnt--)putchar(ch[cnt]);
}
inline void unsigned_print(__int128 x)
{
    if(!x){putchar('0');return;}
    register short cnt=0;
    char ch[42];
    while(x)ch[cnt++]=x%10+48,x/=10;
    while(cnt--)putchar(ch[cnt]);
}

//wait to be updated

鸣谢


发表于 2019-08-11 22:10:29 in IO