使用更快的I / O方法

时间:2014-06-04 20:13:49

标签: c++ c iostream getchar

我正在研究编程问题的更快的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;             
}

3 个答案:

答案 0 :(得分:4)

代码具有字符'0''9'的硬编码ASCII值,因此它会跳过不在该范围内的任何内容(第四个感兴趣的四行中的循环)你)。

然后,当它看到'0' - '9'范围内的字符时,它会将其运行总数乘以10(将其向左移动一次使其加倍,然后将其添加到自身左移三次,其中就像乘以8)并添加当前的char - '0'的代码。

答案 1 :(得分:1)

该行

for(;(c<48 || c>57);c = gc());  

读取不在'0''9'之间的字符。

该行

for(;c>47 && c<58;c = gc())   

逐个读取'0''9'之间的字符。

该行

{x = (x<<1) + (x<<3) + c - 48;}   

简单等同于

x = 10 * x + c - 48;  

此功能的简化版本可以改写为:

#define gc getchar_unlocked
int read_int()
{
    char c = gc();
    while(c<'0' || c>'9')
       c = gc();
    int ret = 0;
    while(c>='0' && c<='9')
    {
        ret = 10 * ret + c - 48;
        c = gc();
    }
    return ret;
}  

答案 2 :(得分:1)

'0'的ASCII值为48,每个后续数字再增加一个。即'1' - &gt; 49,'2' - &gt; 50 ......依此类推。

这样做的一个副作用是,如果你取一个字符数字,意思是'0''9'之间的某个字符,并从中减去'0'的ASCII值,那么你得到了该数字的整数值。

因此,在x = (x<<1) + (x<<3) + c - 48;行中,c-48部分正在将数字字符(ASCII编码字符)转换为引用该字符的0-9之间的数字。

(x<<1)+(x<<3)x * 10相同,(有关详细信息,请结帐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。