提问人:Sidak 提问时间:6/5/2014 最后编辑:Sidak 更新时间:1/22/2015 访问量:2283
使用更快的 I/O 方法
working of a faster I/O method
问:
我正在研究更快的 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;
}
答:
该代码对 chars 和 进行了硬编码的 ASCII 值,因此它会跳过不在该范围内的任何内容(您感兴趣的四行中的第一个 for 循环)。'0'
'9'
然后,当它看到 - 范围内的字符时,它会将其运行总数乘以 10(通过将其向左移动一次以使其加倍,然后将其向左移动三次,这就像乘以 8 一样)并添加当前字符 - 的代码。'0'
'9'
'0'
线
for(;(c<48 || c>57);c = gc());
读取不介于 之间的字符。'0'
'9'
线
for(;c>47 && c<58;c = gc())
逐个读取 TO 之间的字符。'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;
}
的 ASCII 值为 48,每个后续数字多一个。即 ->49、->50......等等。'0'
'1'
'2'
这样做的副作用是,如果你取一个字符数字,意思是介于 和 之间的内容,并从中减去 的 ASCII 值,那么你就会得到该数字的整数值。'0'
'9'
'0'
因此,在该行中,该部分将数字字符(ASCII编码字符)转换为0-9之间的数字,该数字表示该字符。x = (x<<1) + (x<<3) + c - 48;
c-48
(x<<1)+(x<<3)
与 ,(有关更多信息,请查看 http://en.wikipedia.org/wiki/Multiplication_algorithm#Shift_and_add 和 How can I multip and divide using only bit shift and add??) ) 实际上,这部分代码被不必要地混淆了。编译器可以通过许多不同的方式优化乘法,使其尽可能快,因此我们不需要手动实现位移。不过,这是一个有趣的大学水平的谜题。x * 10
for(;(c<48 || c>57);c = gc());
此循环将忽略所有字符,直到它收到一个落在 to 范围内的字符。因此,如果用户通过键入空格或任何其他字符开始,它将被忽略。'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。
评论
char
int
c<48 || c>57
c<'0' || c>'9'