scanf读取%d时输入仅负号为何失败却消耗符号?
scanf读取数值时符号被消耗但返回匹配失败的原因
测试代码
int x; int ret = scanf("%d", &x); char ch; scanf("%c", &ch); printf("%c, %d\n", ch, ret);
输入与输出
- 输入:
-*
- 输出:
*, 0
疑问
输入-*时,首次读取整数x返回0(匹配失败),但负号被消耗;换成正号也会出现相同情况,但其他字符不会。请问该符号是否被视为整数的开头?若是为何判定失败?若不是为何被消耗?还是未定义行为?另外使用double类型时输入.也会出现相同问题。
解析
这是scanf的标准规定行为,并非未定义行为。
针对整数格式%d的情况
- scanf处理
%d时,会先跳过空白字符,然后尝试匹配整数的可选符号(+或-),之后需要匹配数字字符来构成完整整数。 - 当输入是
-*时,scanf会先读取-(因为它是整数的合法起始符号),但后续的*不是数字,无法构成有效整数,因此匹配失败。此时scanf会把*放回输入缓冲区,但已经读取的-不会回退——这就是第二个scanf("%c")读取到*而非-的原因。 - 这种场景下,scanf返回0,表示没有成功匹配任何完整的输入项(因为有效整数未被读取完成)。
针对浮点数格式%lf的情况
- 浮点数的合法起始包括:可选符号、数字,或者单独的
.(比如.123是合法的浮点数)。当输入.后跟随非数字字符时,scanf会读取.,但后续无法匹配数字,导致匹配失败,.被消耗,剩余字符留在缓冲区。
总结
+/-是整数的合法起始部分,.是浮点数的合法起始部分;- 当这些符号后没有跟上合法的数字时,scanf会消耗这些符号,但因无法构成完整的数值,所以返回匹配失败;
- 这完全是C标准规定的scanf匹配逻辑,属于预期行为。
内容的提问来源于stack exchange,提问作者GKxx
相关产品推荐
相关产品推荐

