我正在研究用于编程问题的更快的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_addHow 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。这是cx中的值将如何递增的方式。

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/

10-13 09:08