【问题标题】:Why is adding a leading space in a scanf format string recommended?为什么建议在 scanf 格式字符串中添加前导空格?
【发布时间】:2014-12-11 01:21:19
【问题描述】:

我目前正在阅读《C11 初学者编程》这本书,在 scanf() 章节中它说:

“始终在第一个控制字符串字符之前添加一个前导空格,以确保准确的字符输入。”如:

scanf(" %s", whatever);

控制字符串" %s",前面有一个空格。 我知道这听起来很不言自明,但我真的不明白可能出了什么问题,以及这个空间如何确保准确的字符输入。

【问题讨论】:

  • 最好附带一个大警告 Single char %c fetching 可能是该大锤声明背后的主要理由,并且未能提供这样的细节让我质疑巫毒教的教学意识形态文本。 “总是做”没有某种解释为什么你应该遵循这个口头禅,如果你不这样做,事情会如何出错,通常比有帮助(例如,您发布此问题...)。无论如何,您可能会发现 this answer 很有帮助。
  • 那本书真的叫C11 Programming for初学者吗? scanf 在 C11 中不是被 scanf_s 取代了吗?
  • @AndersMarziTornblad: 否。scanf_s()Annex K §3.5.3.4 The scanf_s function 中定义的可选函数。微软宁愿你使用他们的scanf_s() 版本,但很少有其他编译器/库实现了它。这些函数的签名一致,_s(更安全)函数无法保证这一点。
  • "%s" 表示:忽略可选的前导空格并读取空格分隔的字符串..." %s" 表示忽略可选的空格,然后忽略可选的前导空格并读取空格分隔的字符串。

标签: c string controls scanf


【解决方案1】:

@WhozCraig 很好地说明了这个建议的缺点。它没有理性也没有细节。此外,它不适用于"%s",因为"%s" 会使用带或不带前导空格的前导空白。

前导空白,无论是' ''\t''\n' 等都做同样的事情:直接scanf() 使用而不存储可选的前导空白char。这很有用,因为以前的 scanf() 的典型用法不会从 Enter

消耗用户的 '\n'
scanf("%d", &some_int);
scanf("%c", &some_char);  // some_char is bound to get the value '\n'

所有scanf() 输入说明符都忽略前导空格,除了3:"%c""%n""%[]"

简单指令 do 受益于前导空格,如下所示。在'$' 之前使用之前剩余的空白。

int Money;
scanf(" $%d", &Money);

通常,尽管并非总是如此,"%c" 之前的前导空格在读取用户输入的单个 char 时是有益的。

char ch;
scanf(" %c", &ch);

该建议最大的错误在于 1) 在使用 "%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() — 通常情况下如此。

【讨论】:

  • 谢谢 chux :) 据我了解,当使用带有“%c”、“%n”或“%[]”的 scanf() 时,scanf 会将前导空格存储在字符。如果一个 char 只能容纳一个字符,它如何存储在同一个 char 中?
  • @Stanley scanf(" %c", &ch); 将消耗并丢弃可选的前导空白。然后将在ch 中存储一个非空白charscanf("%c", &ch); 会将第一个 char 存储到 ch 中。 "%n""%[]" 的工作方式完全不同。
  • 非常好的答案,感谢您为本网站所做的努力!
【解决方案2】:

“始终在第一个控制字符串字符之前添加一个前导空格,以确保准确的字符输入。”

这是在scanf 读取用户输入之前,消耗stdin 中可能由先前用户输入(如carriage return)留下的任何尾随空白字符或前导空白字符。当然,除了%c%[…](扫描集)和%n 之外的所有转换都会自动执行此操作,因此建议与%s 并不真正相关。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    • 2018-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多