【问题标题】:Handling of %s by printf function in CC 中 printf 函数对 %s 的处理
【发布时间】:2018-02-17 19:09:01
【问题描述】:

当我使用线条时:

char *sentence = (char *)malloc(100);
scanf("%[^\n]%*c",sentence);

从标准输入读取一行到缓冲区,句子,然后有:

printf("%s\n", sentence);

之后,我注意到 printf 打印了整个句子,而不是只打印该行的第一个单词。为什么是这样? printf 不应该只占用第一个空格吗?如果不是,它怎么知道在哪里停下来?句子肯定不会以“\n”结尾,因为它不读取最后一个返回值,我们使用 *c 读取一个字符而不是存储它。

【问题讨论】:

  • 1. malloc 的演员阵容不好stackoverflow.com/questions/605845/…
  • 2.也许阅读 scanf 的手册页linux.die.net/man/3/scanf
  • 'printf()' 中的 '%s' 将输出到一个 NUL 字节。它不会停留在“空白”处
  • 在调用任何scanf() 系列函数时: 1) 始终检查返回值(而不是参数值)以确保操作成功。 2) 当使用输入/格式说明符%[...] 和/或%s 时,始终包含一个比输入缓冲区长度小1 的MAX CHARACTERS 修饰符,因此输入缓冲区不会溢出(注意:这两个输入/格式说明符总是将 NUL 字节附加到输入。)如果传入的字符溢出输入缓冲区,结果是未定义的行为,并可能导致段错误事件。
  • 在调用任何堆分配函数(malloc、calloc、realloc)时 1) 始终检查 (!=NULL) 返回值以确保操作成功

标签: c printf buffer scanf


【解决方案1】:

扫描集不包含' ',因此它不会在收到一个时停止。 scanf 将是

scanf("%[^ \n]%*c",sentence);

这基本上会在找到\n' ' 时停止,这样如果它是空格分隔的,你将得到第一个单词。(虽然如果第一个单词之前有空格,那么句子将不会被更新,因为scanf 从扫描集中看到一个字符)注意一件事,你的缓冲区可以容纳 100 个字符(由char*sentence 指向)所以像这样使用它

scanf("%99[^ \n]%*c",sentence);

比它可以容纳的少一个,因为还有 nul 终止字符要容纳。

此外,如果你想得到一个单词,你可以做一些更简单的事情:-(这个解决方案适用于单词前缀为空格的情况,因为%s 格式说明符跳过它们并存储非-whitespace 直到遇到空白字符或扫描长度指定的最大字符)

scanf("%99s",sentence);

【讨论】:

  • 嗯,%s 无论如何都会在第一个空格处停止。
  • @WeatherVane.:已编辑。
  • "这样你会得到第一个单词,如果它是空格分隔的" --> 如果第一个单词有前面的空格,那么sentence 不会更新。避免使用scanf("%[^\n]...
  • @WeatherVane "%s 在第一个空格处停止" -- 几乎。 "%s" 消耗前导空白,(它不会停止),然后扫描/保存非空白。然后在后面的第一个空格处停止。
  • @coderredoc 使用"scanf(" %[^\n]..."comment 的问题得到缓解。
猜你喜欢
  • 1970-01-01
  • 2014-04-13
  • 1970-01-01
  • 1970-01-01
  • 2012-09-24
  • 1970-01-01
  • 2015-02-15
  • 2016-10-01
  • 2017-01-17
相关资源
最近更新 更多