我正在研究用于编程问题的更快的I / O方法,
我发现了使用getchar_unlocked()
的这种方法(虽然有风险,但仍然有)。
我环顾了四周,但无法了解它如何扫描整数值
换句话说,这4行是什么意思,以及它们在scanint()
函数中的工作方式
定义如下
#include<iostream>
#include<cstdio>
#define gc getchar_unlocked
void scanint(int &x)
{
register int c = gc();
x = 0;
for(;(c<48 || c>57);c = gc());
for(;c>47 && c<58;c = gc())
{x = (x<<1) + (x<<3) + c - 48;}
}
int main()
{
int n,k;
scanint(n);
scanint(k);
int cnt=0;
while(n--)
{
int num;
scanint(num);
if(num%k==0)cnt++;
}
printf("%d",cnt);
return 0;
}
最佳答案
'0'
的ASCII值为48,随后的每个数字再增加一位。即'1'
-> 49,'2'
-> 50 ...等。
这样做的副作用是,如果您使用一个字符数字,表示'0'
和'9'
之间的某个字符,并从中减去'0'
的ASCII值,那么您将获得该数字的整数值。
因此,在x = (x<<1) + (x<<3) + c - 48;
行中,c-48
部分将数字字符(ASCII编码字符)转换为引用该字符的0-9之间的数字。(x<<1)+(x<<3)
与x * 10
相同(有关更多信息,请 check out http://en.wikipedia.org/wiki/Multiplication_algorithm#Shift_and_add和How can I multiply and divide using only bit shifting and adding? ),实际上这部分代码是不必要的。编译器可以多种方式优化乘法以使其尽可能快,因此我们不需要手动实现移位。虽然这使一个有趣的大学水平的难题。for(;(c<48 || c>57);c = gc());
此循环将忽略所有字符,直到接收到'0'
到'9'
范围内的字符为止。因此,如果用户通过输入空格或任何其他字符开始,它将被忽略。
当代码到达for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}
行时,变量c
已被初始化为用户键入的第一位数字。该循环使初始化为空,因此控制流将直接进入循环并在键入每个字符时开始计算数字。
只要用户继续键入数字,循环就会继续进行,只要用户键入数字以外的其他内容,循环就会终止,并最终确定数字。
在用户继续键入数字之前,x = (x<<1) + (x<<3) + c - 48;
行将一遍又一遍地执行,每次c
都是刚刚键入的字符。 x
将自身乘以10
并添加新数字。
假设用户键入2014。这是c
和x
中的值将如何递增的方式。
c = '2' #ASCII value 50
x = 2
c = '0' #ASCII value 48
x = 20
c = '1' #ASCII value 49
x = 201
c = '4' #ASCII value 52
x = 2014
HTH。
关于c++ - 更快的I/O方法的工作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24046734/