提问人:Amittai Aviram 提问时间:10/22/2023 最后编辑:OkaAmittai Aviram 更新时间:10/24/2023 访问量:100
当第一个格式字符串字符不是空格时 scanf 的行为
Behavior of scanf when first format string character is not whitespace
问:
scanf
应该使用和丢弃格式字符串中不属于转换说明符的任何字符。但是,当非空格、非转换字符出现在格式字符串的第一位时,它的行为似乎有所不同。为什么?
int main() {
int num, num2;
printf("> ");
while (scanf("> %d %d", &num, &num2)) {
printf("You entered the number %d %d.\n", num, num2);
printf("> ");
}
return EXIT_SUCCESS;
}
如果构建并运行此命令,然后输入
> 3 4
在出现提示时,它会打印消息和重复的提示,然后立即退出。
因此,这意味着第一次返回,然后在用户输入另一组令牌之前返回。如果从格式字符串中删除 ,则循环将一直运行,直到用户输入非数字的内容,然后导致返回 - 这是我所期望的行为。scanf
2
0
>
scanf
0
此外,如果我在第一个转换说明符之后放置相同的符号,循环将继续按预期运行。也就是说,如果格式字符串有 , 比如说, ,并且用户输入"%d > %d"
3 > 4
循环将再次运行并接受另一轮输入。
我没有看到任何关于此行为的文档。
答:
从一些文档中:fscanf
格式字符串包括
- 非空格多字节字符,但以下情况除外:格式字符串中的每个此类字符都只使用输入流中的一个相同字符,或者如果流上的下一个字符不相等,则会导致函数失败。
%
虽然说明符使用任何和所有1 个前导空格,但它不会使用它后面的换行符,并且在后续迭代中与该换行符 () 不完全匹配。fscanf
%d
'>'
'\n'
来自同一文档:
- 空格字符:格式字符串中的任何单个空格字符都会使用输入中所有可用的连续空格字符(就像通过在循环中调用 IsSpace 来确定一样)。请注意,格式字符串中的 、 、 或其他空格之间没有区别。
"\n"
" "
"\t\t"
因此,格式说明符中的前导空格将使用输入中的尾随换行符:
#include <stdio.h>
int main(void)
{
int num, num2;
while (1) {
printf("Enter \"> NUM NUM2\": ");
if (2 != scanf(" > %d %d", &num, &num2))
break;
printf("You entered the number %d %d.\n", num, num2);
}
}
Enter "> NUM NUM2": > 1 2
You entered the number 1 2.
Enter "> NUM NUM2": > 3 4
You entered the number 3 4.
顺便说一句:这将永远循环在 的真实返回值上(负数,几乎普遍):EOF
int
-1
while (scanf("> %d %d", &num, &num2))
您应该显式检查 的返回值是否为转换说明符的预期数量(即 )。scanf
2
1. 除 %c、%[ 和 %n
之外的所有格式说明符也是如此(假设未发生错误)。
评论
"%c"
"%[..]"
"%n"
" > %d %d"
scanf
我大体上同意所有的评论,尤其是那些强调用户输入并不是一个好主意的评论。scanf
你的问题的答案也大多是给出的,在第一个输入中,一个尾随的换行符“字符”被添加到输入流中,它不会被解析并保留在那里,在第二个循环中,换行符将与说明符中的第一个字符匹配,在这种情况下,它将无法匹配, 返回 0,打破循环。Enter
scanf
>
scanf
正如建议的那样,在说明符中添加前导空格将强制使用所述换行符并清除输入缓冲区,该缓冲区将再次等待输入,从而暴露此行为。scanf
评论
scanf
'>'
" > %d %d"
while (scanf("> %d %d", &num, &num2) == 2)
sscanf()
scanf()
scanf()
scanf()
fgets()
"unrealated:"
'\n'
[Enter]
'>'
== 2
fgets()
scanf()