我目前正在阅读的这本书是《C11编程入门》,在scanf()章节中提到:
“始终在第一个控制字符串字符之前添加一个前导空格,以确保准确的字符输入。” 例如:
scanf(" %s", whatever);
控制字符串
" %s"
前面有一个空格。
我知道这听起来很简单明了,但我不太明白可能会出现什么问题,以及这个空格如何确保准确的字符输入。@WhozCraig非常明确地指出了这条建议的缺点。它没有合理性,也没有细节。此外,它不适用于"%s"
,因为"%s"
会在有或没有前导空格的情况下消耗前导空格。
前导空格,无论是' '
、'\t'
、'\n'
等,都有同样的作用:直接让scanf()
消耗而不存储可选的前导空格char
。这在以前的scanf()
的典型使用中非常有用,因为它不会消耗用户的Enter。
scanf("%d", &some_int);
scanf("%c", &some_char); // some_char is bound to get the value '\n'
scanf()
输入说明符都忽略前导空格,除了三个:"%c"
,"%n"
,"%[]"
。'$'
之前会消耗前面剩余的空白。int Money;
scanf(" $%d", &Money);
"%c"
前加上一个空格是有益的,但并非总是如此。char ch;
scanf(" %c", &ch);
"%s"
时,提供一个宽度参数是确保代码稳健性必要的,2)应该检查返回值。char buf[30];
int cnt = scanf("%29s", buf);
if (cnt != 1) Handle_NoInput_or_EOF_IOError();
%c
、%[…]
(扫描集)和%n
之外的所有转换说明符都会自动跳过前导空格,因此该建议实际上与%s
、%d
或%lf
等无关。fgets()
而不是scanf()
。scanf(" %c", &ch);
会忽略前导空格并将非空格字符存储在 ch
中。而 scanf("%c", &ch);
则将第一个出现的字符存储在 ch
中。"%n"
或 "%[]"
的工作方式截然不同。 - chux - Reinstate Monica“在第一个控制字符串字符之前始终添加一个前导空格,以确保准确的字符输入。”
这是为了消耗可能由先前用户输入(如回车符
)留下的stdin
中的任何尾随空格字符或前导空格字符,然后scanf
读取用户输入。当然,除了%c
、%[…]
(扫描集)和%n
之外的所有转换都会自动执行此操作,因此这个建议对于%s
并不重要。
%c
获取很可能是该过度强调语句背后的主要原因,未提供具体细节使我质疑该文本的巫术教学思想。一个没有任何解释的 "总是做<blah>" 的说法,不说明为什么你应该遵循这个口号,以及如果你不这样做会出现什么问题,往往比有帮助的更令人困惑(就像你发这个问题一样...)。无论如何, 您可以在这个答案中找到帮助。 - WhozCraigscanf
不是被scanf_s
所取代了吗? - Anders Marzi Tornbladscanf_s()
是一个可选函数,定义在附录K §3.5.3.4《scanf_s
函数》中(http://port70.net/~nsz/c/c11/n1570.html#K.3.5.3.4)。微软更希望您使用他们自己的版本scanf_s()
,但很少有其他编译器/库实现它。这些函数的签名是一致的,这与_s
(更安全)函数不同。 - Jonathan Leffler"%s"
的意思是:忽略可选的前导空格并读取以空格分隔的字符串..." %s"
的意思是忽略可选的空格,然后忽略可选的前导空格并读取以空格分隔的字符串。 - pmg