scanf()如何检查输入是整数还是字符?

scanf()如何检查输入是整数还是字符?,c,scanf,C,Scanf,我想知道当一个字符本身只是一个数字时,当我们调用scanf(“%d”,&var)时,标准C库函数scanf()如何检查输入是一个整数还是一个字符? 我知道,当它遇到一个非整数时,它会将其放回输入缓冲区并返回-1,但它如何知道输入不是整数?输入总是一个字符串。如果scanf需要一个整数(因为您传递了它“%d”),它会尝试将字符串转换为整数。它尝试从流的开头解析一个有效的十进制整数,实际上是可选的+或-然后是一个或多个数字的序列。它基本上使用了如下循环: while (isdigit((ch=get

我想知道当一个字符本身只是一个数字时,当我们调用scanf(“%d”,&var)时,标准C库函数scanf()如何检查输入是一个整数还是一个字符?
我知道,当它遇到一个非整数时,它会将其放回输入缓冲区并返回-1,但它如何知道输入不是整数?

输入总是一个字符串。如果
scanf
需要一个整数(因为您传递了它
“%d”
),它会尝试将字符串转换为整数。

它尝试从流的开头解析一个有效的十进制整数,实际上是可选的+或-然后是一个或多个数字的序列。

它基本上使用了如下循环:

while (isdigit((ch=getchar()))
    // ...

您误解了
%d
格式说明符。它不返回输入字符的ASCII值(您可以使用
%c
);它返回字符表示的整数。因此,在输入字符
'9'
上,
%d
返回值9,而不是
'9'
的ASCII值


(嗯,
%d
实际上是查看一个字符序列,因此如果输入是
'9'
,然后是
'0'
,然后是
'
,它将解释为90)。

每个字符实际上都表示为一个8位整数,这是正确的。解决方案很简单:看看这个数字,看看它是否在48-57范围内,这是字符“0”-“9”的SCII代码范围


scanf()
的第1315行开始,我们可以看到它的作用
scanf()
实际上更复杂,但它也会查看多字节字符来确定数值。第1740行是魔法发生的地方,这个角色实际上被转换成了一个数字。最后,这可能是最有用的,函数执行循环以执行转换。

基本上,
scanf
函数根据您传递的转换说明符匹配正则表达式。如果指定
%d
,则告诉
scanf
将输入与正则表达式相匹配,正则表达式是介于
'0'
'9'
之间的一个或多个字符(可选带前导
+
-
字符)。然后将该字符序列转换为等效的整数值

非常简单的版本可能如下所示:

while (isdigit(c = fgetc(stream))
  val = val * 10 + valueOf(c); 
ungetc(c, stream);

其中,
isdigit
是一个标准库函数,如果字符值表示十进制数字,它将返回true(非零);而
valueOf
是一个用户定义的函数,它将表示整数的字符(
'0'
-
'9'
)映射到等效的整数值(
0
-
9
)(我不知道有一个标准的库函数可以对单个字符值执行此操作)。为什么不直接从
c
中减去
'0'
,得到等效的整数值?根据编码方式,不能保证所有十进制整字符都是按顺序排列的(所有的世界都不是ASCII);最好将实际转换委托给知道当前编码的函数。

在scanf语句中,您提到的是%d,它只保存整数,因此默认情况下它理解变量为整数

,但无论我们输入什么,它都将是一个ascii值序列,都是数字。不是?表示你的意思是nt数字。scanf接受字符“9”,决定它代表一个数字,并将其转换为整数9。是的,这是它应该做的。键盘将只发送ascii字符。你能解释一下它是如何解析的吗?例如,它将如何区分a和值65,因为a将作为其ascii值65传递e?呃,scant试图读取十进制整数的ASCII表示形式。字母a不是这种表示形式的一部分。