我想知道下面的功能。
inline int nextInt()
{
register int s = 0, ch;
for (ch = getchar(); ch < '0' || ch > '9'; ch = getchar());
for (s = ch - '0', ch = getchar(); ch >= '0' && ch <= '9'; ch = getchar())
s = s * 10 + ch - '0';
return s;
}
我知道这个函数通过返回整数值来行为scanf函数。但是,我没有理解函数的详细过程,因为许多变量都在for循环中,而且我对它的理解有点困惑。即使我将它们复制并粘贴在我的visual studio上,并通过printf查看变量中的每个值,但我都不知道它们在做什么。
你可以向我解释一下他们一行一行的上述代码吗?
答案 0 :(得分:4)
for (ch = getchar(); ch < '0' || ch > '9'; ch = getchar());
读取并忽略字符,直到它获得0-9范围内的某些内容。
for (s = ch - '0', ch = getchar(); ch >= '0' && ch <= '9'; ch = getchar())
s = s * 10 + ch - '0';
将最后读取的ascii字符的数值存储到s中(例如,'1'将1放入s中)。然后它将下一个字符读入ch。然后它测试ch是否是数字。如果是这样,它将s的现有值乘以10并添加ch的数值。现在它读取另一个角色并再次进行测试。
如果键入123,则显示“1”并将1存储为s。然后它读为'2',将s(1)乘以10(10)并加2(12)。然后它读为'3',将s(12)乘以10(120)并加3(123)。
答案 1 :(得分:2)
register int s = 0, ch;
register
关键字是一个过时的存储说明符,告诉编译器在处理器寄存器中保留一个值(过时,因为现在编译器非常善于自己做出决定,并且无论如何都会忽略register关键字)。
从这个关键字的存在,我得出结论,这是非常古老的代码。对于任何现代编译器,上面的代码都可以安全地替换为
int s = 0, ch;
for (ch = getchar(); ch < '0' || ch > '9'; ch = getchar());
让我们将其重写为等效的while
循环:
ch = getchar();
while (ch < '0' || ch > '9')
{
ch = getchar();
}
现在更容易看到它的作用:它读取一个字符,只要它不是数字,就丢弃它并读取下一个字符。
以DRY的名义(不要重复自己),最好使用do while循环编写:
do
{
ch = getchar();
} while (ch < '0' || ch > '9');
for (s = ch - '0', ch = getchar(); ch >= '0' && ch <= '9'; ch = getchar())
s = s * 10 + ch - '0';
让我们再用等效的while循环替换它:
s = ch - '0', ch = getchar();
while (ch >= '0' && ch <= '9')
{
s = s * 10 + ch - '0';
ch = getchar();
}
s = ch - '0', ch = getchar()
只是两个与逗号运算符结合的表达式语句。逗号运算符在计算后忽略其第一个参数的值,并返回第二个参数的值。它在这里使用是因为for
中只能有一个初始化语句,并且由于某种原因,该代码的作者认为他必须在那里填充。所以我们现在将其分为两个陈述:
s = ch - '0';
ch = getchar();
表达式ch - '0'
只是计算数字的值。这使用了类型char
实际上是整数类型的事实,0
实际上是数字0
的字符代码。它还利用了字符集中所有十个数字都是连续的要求。
变量s
存储到目前为止读取的整数。由于到目前为止只读取了一个数字,所以到目前为止读取的整数只是我们读取的数字的值。
这里的第二个声明当然只是读取下一个字符。
只要读取的下一个字符仍为数字,循环就会立即运行。
声明
s = s * 10 + ch - '0'
有效地将下一个数字附加到s
。乘以10只是“追加零”,然后加上(ch - '0')然后用数字值替换最后的0。
请注意,为了避免在读取接近INT_MAX
的数字时出现溢出(以及因此未定义的行为),这应该实际读取
s = s * 10 + (ch - '0');
或者,鉴于此代码只能读取正数,作者可能只使用了无符号类型,因为溢出行为已明确定义。
答案 2 :(得分:1)
好的,让我们分解一下:
inline int nextInt()
inline
关键字是编译器的一个提示,这个函数很小,应该是&#34;内联&#34; (基本上是将函数插入源代码而不是将其作为函数调用的一点优化。)
register int s = 0, ch;
register
关键字,对于所有实际意图和目的,在99.99%的情况下,在语义上毫无意义,使此行等同于int s = 0, ch;
。
for (ch = getchar(); ch < '0' || ch > '9'; ch = getchar());
这条线有点傻。它实际上是在调用getchar()
两次,这意味着它可以拉入(可能)两个字符,比较其中一个字符以确保它在0到9之间,并且如果它不是,则继续运行。吨。写这个的更好方法可能是do ch = getchar(); while (ch < '0' || ch > '9');
。
for (s = ch - '0', ch = getchar(); ch >= '0' && ch <= '9'; ch = getchar())
s = s * 10 + ch - '0';
这两行实际上只要用户继续输入整数,就会将s
乘以10,同时将新整数推入到one列中。如果用户输入8 1 3 4
,则生成的整数将为8134。