关于在C中从用户处获取输入的查询

关于在C中从用户处获取输入的查询,c,C,这里我指的是来自“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'); ret

这里我指的是来自“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')这条线在做什么


对于完整代码访问:

如果输入是
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'(字符)=(int)1
?这种转换是如何发生的?从
char
int
:是因为我们分配给一个整数容器,即
int n


如上所述,
'0'
和“
1
”等字符常量在C语言中是整数常量(在C++中它们应该是
char
常量),而
'0'
'1'
的值通常分别是48和49(但C标准并不保证!)。因此,
49-48
当然给出了
1

如果输入是
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'(字符)=(int)1
?这种转换是如何发生的?从
char
int
:是因为我们分配给一个整数容器,即
int n


如上所述,
'0'
和“
1
”等字符常量在C语言中是整数常量(在C++中它们应该是
char
常量),而
'0'
'1'
的值通常分别是48和49(但C标准并不保证!)。所以,
49-48
当然给出了
1

'1'-'0'(char)=(int)1???这种转变是如何发生的??从char到int。是因为我们分配给一个整数容器吗?i、 e int n??字符常量(如
'0'
)实际上具有C中的
int
类型。此外,如果将较小整数的值赋给较大整数类型的变量,则该值会自动提升。将
char
类型或
short
类型的
1
转换为
int
类型或
long
类型的
1
…将不会
scanf()
功能也
ungect('\n')
?顺便说一句:我认为取消ETC(EOF)C117.21.7.10.4“如果c的值等于宏EOF的值,则操作失败,输入流不变”是可以的。因此建议删除
如果(c!=EOF&&c!='\n')
。进一步简化想法:更改为
而(isdigit(c=fgetc(stdin))
isdigit(EOF)
返回0。@chux:我在编写代码时考虑到了这一点,决定我不喜欢它,也不会那样写。你是对的;这是可以做到的。然而,我不认为它是一种好的风格,因为它是正确的。“1”-“0”(字符)=(int)1???这种转变是如何发生的??从char到int。是因为我们分配给一个整数容器吗?i、 e int n??字符常量(如
'0'
)实际上具有C中的
int
类型。此外,如果将较小整数的值赋给较大整数类型的变量,则该值会自动提升。将
char
类型或
short
类型的
1
转换为
int
类型或
long
类型的
1
不需要努力…将不会
scanf()