读入优化&输出优化

匿名 (未验证) 提交于 2019-12-02 23:48:02

注意了注意了注意了,重要的事情说3遍,这个东西是骗分神器,骗分神器,骗分神器!!!
众所周知:scanf比cin快得多,printf比cout快得多,如果你不知道就……就现在知道了
那有没有更快的呢?当然。
请看:


好吧,这就是读入优化的效果,在数据很恐怖的情况下能比scanf多过1-5个点……
比如说这种:

都说了要读入优化你还不读入优化,那不是找死吗……

前面都是废话,现在开始说正事

读入优化

首先,读入优化这里是只是针对整数,getchar读字符是非常快的,所以我们就用getchar了。(下面都假设输入的数为x)

负数处理

很简单,用一个标志变量f,开始时为1,当读入了’-’时,f变为-1,最后x*=f即可

绝对值部分处理

显然getchar每次只能读一位,所以,每当读了一位时x*=10,为这一位“留位置”。
举个例子:现在读入了123,x为123,再读入了一个4,x*=10,变为了1230,现在它的最后一位空出来了,正好留给4,x+=4,x就变为了1234,当然,这里的’4’是char类型,需要减去’0’才是4,即:x=x*10+s-'0'(s为当前输入的字符)

关于细节

很多时候是有多余空格或者其他的乱码字符输入,为了防止bug,我们要严谨~详见代码。

代码

 1 void read(int &x)//'&'表示引用,也就是说x是一个实参,在函数中改变了x的值就意味着在外面x的值也会被改变  2 {  3     int f=1;//标记正负  4     x=0;//归零(这就是潜在bug,有可能传进来时x没有归零)  5     char s=getchar();//读入第一个字符  6     while(s<'0'||s>'9')//不是数字字符  7     {  8         if(s=='-')//不能直接把f=-1,有可能输入的不是'-'而是其他乱七八糟的东西  9             f=-1; 10         s=getchar();//继续读 11     } 12     while(s>='0'&&s<='9')//是字符(一旦不是字符就意味着输入结束了) 13     { 14         x=x*10+s-'0'; 15         s=getchar(); 16     } 17     x*=f;//改变正负 18 }

简洁一些:

1 void read(int &x) 2 { 3     int f=1;x=0;char s=getchar(); 4     while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} 5     while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} 6     x*=f; 7 }

这就是完整的读入优化了,你可以直接这样用:

1 int N; 2 read(N);

当然还有更装逼的代码:

1 #define num ch-'0' 2 void get(int &res){ 3     char ch;bool flag=0; 4     while(!isdigit(ch=getchar())) 5         (ch=='-')&&(flag=true); 6     for(res=num;isdigit(ch=getchar());res=res*10+num); 7     (flag)&&(res=-res); 8 }

这个就真的很跳了。
首先:isdigit是判断一个字符是否为数字字符,需要头文件#include<cctype>,刚刚忘了说,getchar需要cstdio。
然后,那个诡异的(ch=='-')&&(flag=true)和(flag)&&(res=-res);是个什么玩意?我们发挥聪明才智,想起&&是“短路运算符”,短路运算符是啥?就是看到第一个条件错误就不会执行第二个条件,直接跳过了,所以这两句代码就不难理解了,唯一颠覆宝宝们的认知的是&&可以脱离if和return什么的直接用……

输出优化

如果有50%的人知道输入优化,那知道输出优化的最多不过20%,输出还能怎么优化?putchar啊!putchar是比printf快的。(下面都假设输出的数为x)
ps:居然还有putchar这种东西?!

负数处理

输出就简单了,如果是负数,直接putchar('-');x=-x;即可,不解释。

绝对值部分处理

这里是不是还是用循环呢?答案是――否定的,为了极致的速度,我们用递归!递归什么?递归下一位啊,即x/10,然后,注意边界,x要>9才能继续递归,否则要输出x%10(因为还有最后一位)。

关于细节

无……

代码

 

至于输出优化,目前还没发现什么太跳的,毕竟写输出优化的就少。


Test.cpp:

 1 #include<cstdio>  2 #include<ctime>  3 #include<windows.h>  4 using namespace std;  5 #define TIMES 1000000  6 double A[5];  7 void print(int x)  8 {  9     if(x<0)putchar('-'),x=-x; 10     if(x>9)print(x/10); 11     putchar(x%10+'0'); 12 } 13 void read(int &x) 14 { 15     int f=1;x=0;char s=getchar(); 16     while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} 17     while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} 18     x*=f; 19 } 20 int main() 21 { 22     freopen("in.txt","r",stdin); 23     freopen("111.txt","w",stdout); 24     int a; 25     double t1,t2; 26     t1=clock(); 27     for(int i=1;i<=TIMES;i++) 28         scanf("%d",&a); 29     t2=clock(); 30     A[1]=(t2-t1)/1000; 31     t1=clock(); 32     for(int i=1;i<=TIMES;i++) 33         read(a); 34     t2=clock(); 35     A[2]=(t2-t1)/1000; 36     t1=clock(); 37     for(int i=1;i<=TIMES;i++) 38         printf("%d",a); 39     t2=clock(); 40     A[3]=(t2-t1)/1000; 41     t1=clock(); 42     for(int i=1;i<=TIMES;i++) 43         print(a); 44     t2=clock(); 45     A[4]=(t2-t1)/1000; 46     fclose(stdout);//为了不输出前面一堆东西 47     freopen("out.txt","w",stdout); 48     printf("Scanf:  %.4lf S\n",A[1]); 49     printf("Read:   %.4lf S\n",A[2]); 50     printf("Printf: %.4lf S\n",A[3]); 51     printf("Print:  %.4lf S",A[4]); 52 }

Data.cpp:

 1 #include<cstdio>  2 #include<ctime>  3 #include<cstdlib>  4 #define TIMES 1000000  5 #define MAXN 100000  6 int main()  7 {  8     srand(time(NULL));  9     freopen("in.txt","w",stdout); 10     for(int i=1;i<=TIMES*2;i++) 11     { 12         if(rand()%2) 13             printf("-"); 14         printf("%d\n",rand()%MAXN); 15     } 16 }


以下是我的测试结果(测5次,数据一模一样):







这里用了1000000组数据,输入优化比scanf快了约0.2秒,也就是说,每50万组数据读入优化要快0.1秒(100ms),刚好符合了最开始的数据范围。



作者:∞∑
来源:CSDN
原文:https://blog.csdn.net/c20190102/article/details/69710341
版权声明:本文为博主原创文章,转载请附上博文链接!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!