【发布时间】:2011-04-12 01:38:29
【问题描述】:
我想知道当字符本身只是一个数字时,当我们调用 scanf("%d",&var) 时,标准 C 库函数 scanf() 如何检查输入是整数还是字符? 我知道当它遇到非整数时,它会将其放回输入缓冲区并返回 -1,但它如何知道输入不是整数?
【问题讨论】:
我想知道当字符本身只是一个数字时,当我们调用 scanf("%d",&var) 时,标准 C 库函数 scanf() 如何检查输入是整数还是字符? 我知道当它遇到非整数时,它会将其放回输入缓冲区并返回 -1,但它如何知道输入不是整数?
【问题讨论】:
您是正确的,因为每个字符实际上都表示为一个 8 位整数。解决方法很简单:查看那个数字,看看它是否在 48-57 范围内,即字符 '0' - '9' 的 SCII 代码范围。
从scanf()source code 的第 1315 行开始,我们可以看到这一点。不过,scanf() 实际上更复杂 - 它还查看多字节字符来确定数值。第 1740 行是魔法发生的地方,该字符实际上被转换为一个数字。最后,这可能是最有用的,strtol() 函数会循环执行该转换。
【讨论】:
输入总是一个字符串。如果scanf 需要一个整数(因为您将它传递给"%d"),它会尝试为您将字符串转换为整数。
【讨论】:
在 scanf 语句中,您提到 %d 仅保存整数,因此默认情况下它理解变量为整数
【讨论】:
基本上,scanf 函数会根据您传递的转换说明符匹配正则表达式。如果您指定%d,则告诉scanf 将输入与'0' 和'9' 之间的一个或多个字符(可选以+ 或- 字符开头)的正则表达式匹配。然后它将该字符序列转换为等效的整数值。
一个非常简单的版本可能看起来像这样:
while (isdigit(c = fgetc(stream))
val = val * 10 + valueOf(c);
ungetc(c, stream);
其中isdigit 是标准库函数,如果字符值表示十进制数字,则返回真(非零),valueOf 是映射表示整数的字符的用户定义函数('0' - '9') 到等效的整数值 (0 - 9)(我不知道有一个标准库函数对单个字符值执行此操作)。为什么不直接从c 中减去'0' 以获得等效的整数值?根据编码,不能保证所有十进制整数字符都会按顺序排列(All The World Is Not ASCII);最好将实际转换委托给知道当前编码的函数。
【讨论】:
它尝试从流的开头解析一个有效的十进制整数,实际上是可选的 + 或 - 然后是一个或多个数字的序列。
【讨论】:
它基本上使用如下循环:
while (isdigit((ch=getchar()))
// ...
【讨论】:
您误解了%d 格式说明符。它确实不返回输入字符的ASCII值(你可以使用%c);它返回字符表示的整数。因此,在'9' 的输入字符上,%d 返回值 9,而不是 '9' 的 ASCII 值。
(好吧,%d 实际上是查看一个字符序列,所以如果输入是 '9' 后跟 '0' 后跟 ' ',它将解释为 90)。
【讨论】: