目录
C++选手喜欢用的I/O:cin & cout
但是经过事实证明,cin & cout比scanf & printf明显要慢。cin、cout为什么慢?因为你不需要指定变量的类型,他运用了输入输出流,可以自动判断你输入或输出的内容的类型,而提供这种简便的同时,也牺牲了时间。
C++选手更喜欢用的I/O:scanf & printf
这种C语言中的输入输出方式相比于C++要快的多了,对于NOIP来讲应该是完全足够了,可是如果你要写暴力,那么你就需要争取更多的时间,这时scanf和printf又显得有点慢了。
可是scanf和printf为什么还有点慢?因为他们可以直接输入输出所有类型的变量,因此相比于只能读入整型变量的getchar(),他们还是稍微慢了一些。
读入优化:说到这里我们已经清楚的知道了这篇文章&&读入优化的主角——getchar()
写在前面:getchar()是包含在cstdio库文件中的一个宏,可以也只能直接读取整型变量。getchar()也有缺点,无论空格(32)还是换行符(10),都可以被读入。我们需要数字,而0(48)和9(57)恰好连续,只要ASCII码在48与57之间,就确定是数字了。因为不清楚文件里会给出多少空格,所以要用while循环。
char ch=getchar(); while(ch<'0'&&ch>'9') ch=getchar();
于是当循环结束时,字符c中已经有了一个数字。还是因为不知道数字有多长,所以继续用while。可是作为字符的数字,其本质只是一个符号,和整形变量(int)还是有很大差别。这里又借用ASCII码,0(48),1(49)……8(56),9(57);用当前数字的ASCII码减去0(48),返回的就是一样的数字。
while(ch>='0'&&ch<='9'){ x=(x<<3)+(x<<1)+(ch^48); //x<<3和x<<1分别表示8x和2x,位运算速度相对较快且便于内联。 //ch^48等价于ch-'0' ch=getchar(); }
这里需要注意一点,位运算的优先级我也搞不清楚,所以为了保险起见,请务必给他们带上括号,反正也不费什么功夫(就因为这个括号,调试一道题调了一早上然后发现是读入错了。。。)
那么最后一点,如果读入的都是非负数,那么读入优化的代码到此结束,但如果我们要读入复数怎么办?负号当然是在数字之前,所以只需要特判一下就OK了。所以最后写下来的读入优化就是这个亚子的!
inline int Read(){ int x=0,f=1; 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; }
输出优化:既然有getchar()来读入,就有相对应的putchar()来输出,道理就是读入优化反过来,我就不赘述了。
这里递归输出x/10其实就是与读入优化中的while是一个用途,其他的都是一样的,想必很好理解。
void Print(int x){ if(x<0){ putchar('-'); x=-x; } if(x>9) Print(x/10); putchar(x%10+'0'); }
我参考了zbx orz的博客,这里我恰个饭:https://www.cnblogs.com/qq2940345744/