C/C++如何加速输入输出效率(下)
1.简介
自上一篇文章,我们了解了解除绑定的输入输出流,这会让我们的代码输出变得迅速,然而,对于输入而言,亦有快速读取这一个更优秀的方案(相对来说也较为麻烦)。
在我们学习C语言的时候,我们曾经学过字符的输入函数getchar(),她从标准输入里面读取下一个字符,相当于gets(stdin),返回类型为int型,为用户输入的ASCII码,出错则返回-1。
2.实现方式
将所读取的数据按位进行分段截取,比如读取入123这个数据,在确定所读取的是数字的情况下,先读取数字1,如果其后还有数据,将第一个读取的数据1先乘以10再读取第二个数据2,接着读取3,将前面的12再乘以10,最后就可以读取成功123,而对于负数而言,我们只需要设置一个flag标记,对第一位的读取进行一个特判即可,在读取完这些数据之后,将获取到的整体数据进行返回,这边就是快读的基本思想。
请记住这个核心:判断是否为数字à按位读取à转换ASCII码为数字à继续读取à进行乘10与相加à读取结束返回存储的值
这里有一个简单版本的快读
1 2 3 4 5 6 7 8 | inline int read() { int X=0; bool flag=1; char ch= getchar (); while (ch< '0' ||ch> '9' ) { if (ch== '-' ) flag=0; ch= getchar ();} while (ch>= '0' &&ch<= '9' ) {X=(X<<1)+(X<<3)+ch- '0' ; ch= getchar ();} if (flag) return X; return ~(X-1); } |
使用inline重载函数和重写read(),也可以去掉inline,只不过这样效率稍微慢一些,输入的使用方法就可以照做一般的函数进行使用即可。
1 2 | int tmp=read(); std::cout<<tmp<<std::endl; |
3.扩展,快速输出
通快速读取,亦有快读输出,其思想更为简单,效率也只是略微胜一筹,其思维是,按照每一位进行拆解输出,注意我们需要让在后面的数字后输出,拆解位时就务必要注意,因此,较为简单的方法就是模仿递归进行设计。
1 2 3 4 5 6 | inline void write( int X) { if (X<0) {X=~(X-1); putchar ( '-' );} if (X>9) write(X/10); putchar (X%10+ '0' ); } |
4. 推荐模板
使用C++的万能模板类并创建新的命名空间IO,可以手动指明所需要返回参数的类型,int还是long还是别的,这样的方式更加人性化,可以省去上面那样简单的方式必须手动修改函数类型的缺点,但是这样的模板却更加的复杂和繁长,不易快速上手使用,权且做一个理解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #include<iostream> namespace IO { inline char nc() { static char buf[100000], *p1 = buf, *p2 = buf; return p1 == p2 && (p2 = (p1 = buf) + fread (buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++; } template < typename T> inline T read() { char ch = nc(); T sum = 0; while (!(ch >= '0' &&ch <= '9' )) { ch = nc(); if (ch == EOF) return EOF; } while (ch >= '0' &&ch <= '9' ) { sum = sum * 10 + ch - 48; ch = nc(); if (ch == EOF) return EOF; } return sum; } } using namespace IO; int main(){ long long tmp=read< long long >(); //输入方式 std::cout<<tmp<<std::endl; while (tmp = read< long long >()!=EOF){} //循环判断EOF的方式 return 0; } |
5.本篇后语
C++与STL篇就此结束了,本篇在模式上更趋向于杂谈,STL内容何其多,足足要近千页的书才能讲完讲彻底,因此本章只是提出一个引子,一个简单的介绍,具体的内容和内涵需要多多自学完成,而对于快读和解绑的操作,更加趋向于应用在算法竞赛中抢的速度,具体如何搭配使用,也请自主根据数据规模进行决断。