这里我指的是“codechef.com”中的一个问题。这里下面的代码用于读取用户的初始计数。这将返回一个整数值。
这类似于scanf("%d", &n);
。但是大多数人都在使用这种方法从用户那里获取信息。
我不明白这段代码中的一行,我不明白字符输入转换为整数的位置。
int readuint()
{
int n = 0;
char c = fgetc(stdin);
do {
n = n * 10 + (c - '0');
} while ((c = fgetc(stdin)) != '\n');
return n;
}
有问题的项目是这一行 - n = n * 10 + (c - '0');
这行是做什么的?
答案 0 :(得分:4)
如果输入为123
,则在循环的每次迭代中,它计算:
n = 0 * 10 + ('1' - '0');
n = 1 * 10 + ('2' - '0');
n = 12 * 10 + ('3' - '0');
assert(n == 123);
数字的字符代码始终是连续的,因此'1' - '0'
为1,等等
它将数字的数字转换为数字。习惯成语;你会在C代码中看到很多。
所示代码以各种方式草率:
int readuint()
{
int n = 0;
char c = fgetc(stdin);
do {
n = n * 10 + (c - '0');
} while ((c = fgetc(stdin)) != '\n');
return n;
}
该名称表示它正在读取无符号整数(uint
),但使用的类型是带符号的int
。 c
的类型应为int
,因为fgetc()
(以及getc()
和getchar()
)会返回int
而不是char
。没有办法表明它遇到了EOF。没有防止溢出的保护。输入中没有针对非数字的保护。修复所有这些需要相当多的代码,但代码的基本自我保护意味着它应该更像:
int readint(void)
{
int n = 0;
int c;
while ((c = fgetc(stdin) != EOF && isdigit(c))
n = n * 10 + (c - '0');
if (c != EOF && c != '\n')
ungetc(fp, c);
return n;
}
仍然没有防止溢出的保护,但它对输入中的EOF和非数字有基本保护(通过将其放回下一次读取操作,将新行或EOF以外的字符重新处理)。
'1'-'0' (char) = (int)1
?这种转换是如何发生的?从char
到int
:是因为我们要分配一个整数容器 - 即int n
?
如Elchonon Edelson所述,'0'
和'1
'等字符常量是C中的整数常量(它们在C ++中是char
常量),并且'0'
和'1'
的值通常分别为48和49(但C标准并不保证!)。因此,49 - 48
当然会提供1
。