1

我找到了这个用于快速 I/O 的代码。

    #include <cstdio>

inline void fastRead_int(int &x) {
    register int c = getchar_unlocked();
    x = 0;
    int neg = 0;

    for(; ((c<48 || c>57) && c != '-'); c = getchar_unlocked());

    if(c=='-') {
        neg = 1;
        c = getchar_unlocked();
    }

    for(; c>47 && c<58 ; c = getchar_unlocked()) {
        x = (x<<1) + (x<<3) + c - 48;
    }

    if(neg)
        x = -x;
}

inline void fastRead_string(char *str)
{
    register char c = 0;
    register int i = 0;

    while (c < 33)
        c = getchar_unlocked();

    while (c != '\n') {
        str[i] = c;
        c = getchar_unlocked();
        i = i + 1;
    }

    str[i] = '\0';
}

int main()
{

  int n;
  char s[100];

  fastRead_int(n);
    printf("%d\n", n);

  fastRead_string(s);
    printf("%s\n", s);
  return 0;
}

为什么会有位移 (x<<1) + (x<<3)?另外,当我们输入除 neg 和 numbers 以外的字符时会发生什么?

4

3 回答 3

8

为什么会有位移 (x<<1) + (x<<3)?

左移一位n相当于乘以2^n; 所以这个表达式相当于乘以十(因为2^1 + 2^3 = 2 + 8 = 10)。

代码是这样编写的,因为 (a) 移位和加法比乘法快得多,并且 (b) 编译器不知道乘以 10 的最佳方法。对于大多数现代平台来说,这两个假设都是错误的,所以直截了当

x = x*10 + c - '0';    // '0' is more readable, and portable, than 48.

可能会更快并且更具可读性。

另外,当我们输入除 neg 和 numbers 以外的字符时会发生什么?

第一个循环跳过除“-”和数字以外的任何内容;第二个在遇到非数字时停止(在从流中消耗该字符之后)。因此它将返回它在输入流中找到的第一个十进制整数,如果没有则返回零。例如,如果输入是

xxxx123-456xxx-1234xxx

第一个调用将返回123,第二个456(因为-第一个调用消耗了 ),第三个-1234,以及任何进一步的调用0

于 2013-08-05T15:09:20.613 回答
5

这真是糟糕的代码。首先,为什么是 48 和 57,而不是'0'和 ' 9'。关于您的问题:按位移位用于混淆,并可能减慢速度。该表达式(x << 1) + (x << 3)具有与 相同的数学值10 * x。它的可读性要低得多,并且会干扰一些编译器优化。(在两个移位和加法比乘法更快的处理器上,编译器将为您进行转换,通常比您写出来更好,因为它知道它为什么会移位。)至于你的第二个问题:有问题的代码将跳过所有字符,直到找到数字或减号;它会将类似的东西转换 "abc12"12,而不会出现任何错误。

事实上,正是完全没有错误检查(以及使用getchar_unlocked,而不是getchar),这使得它变得更快。

于 2013-08-05T15:09:19.317 回答
1

该例程结合了读取字符值并在同一操作中将它们转换为整数值(显然要快)。这些变化有助于对值求和。组合移位等于 x10。

于 2013-08-05T15:08:37.693 回答