【问题标题】:What does scanf("%[^\n]%*c", &s); actually do?scanf("%[^\n]%*c", &s); 是什么意思?实际上呢?
【发布时间】:2019-04-14 04:54:10
【问题描述】:

我知道 [^\n] 是一个分隔符,它使 scanf 扫描所有内容,直到按下“输入”键。但我不知道 "%[^\n]%*c" 的其余部分是做什么用的。还有为什么我们在scanf函数中必须提到“&s”而不是“s”。

我试过运行这个:

char s[100];
scanf("%[^\n]s",s);      
scanf("%[^\n]s",&s);

两个上述 scanf 语句对我来说完全一样。如果它们之间有什么区别,那是什么?

还有我为什么更喜欢 scanf("%[^\n]%*c", &s); 对上述声明?

【问题讨论】:

  • 对于已衰减为指针的数组,如您的 scanf 调用中,s&s&s[0] 都引用相同的地址。你从哪里听说你应该更喜欢scanf("%[^\n]%*c", &s);
  • 非常相似,可能与What does `scanf("%*[^\n]%*c")` mean?重复
  • scanf("%[^\n]%*c", &s); 类似于gets()。两者都不使用。而是使用fgets(s, sizeof s, stdin)
  • 你应该更喜欢fgets(),但如果你必须%[^\n]是一个[...](字符类)格式说明符匹配所有'^'的字符('not'当包括第一个)新队。 (允许读取空格)。 '*' 字符是 赋值抑制 修饰符,允许读取/丢弃该 转换说明符 的类型(此处为单个字符,例如 '\n')。当使用'*' 时,不会将任何转换添加到匹配计数(例如返回)。
  • 因为调用后输入缓冲区中剩余的内容不取决于使用的转换说明符(或任何读取/丢弃其他字符)。只需使用 fgets 并通过覆盖 nul-terminating 字符来修剪换行符——这样可以省去很多麻烦。

标签: c scanf


【解决方案1】:

scanf("%[^\n]s",&s);很多麻烦:

不检查返回值。
无超限保护
没有消费'\n'
仅在 '\n' 上没有分配 s
"%[^\n]s"中不需要s
错误类型 &s 的格式。

scanf("%[^\n]s",s); 只少了一个问题(最后一个)。

使用fgets(s, sizeof s, stdin)

if (fgets(s, sizeof s, stdin)) {
  s[strcspn(s, "\n")] = 0; // Lop off potential ending \n
  // Success
} else {
  // failure
}

  • 不检查返回值。

不检查返回值,未知读取成功,s状态不确定。

  • 没有溢出保护

当输入第 100 个字符时会发生什么? - “非常糟糕。不好。不好。” Necron 99, Wizards 1977

  • 没有消费'\n'

'\n' 保留在 stdin 中以破坏下一次读取。

  • 仅在'\n' 上没有分配s

如果输入以'\n' 开头,scanf() 返回并且s 不变。未分配""

  • "%[^\n]s" 中不需要"s"

"s" 不是说明符 "%[^\n]" 的一部分。放下它。

  • &s 的格式错误。

%[...] 匹配 char *,而不是指向 char[100] 的指针,例如 &s (UB)。

【讨论】:

  • 中肯的建议。当然,如果不是因为scanf:):) 的滥用造成的陷阱,SO 会丢失 30% 的问题
  • 我是这里的新手。感谢您迅速而详尽的回答,但是如果您能对列出的要点进行更多解释,那将对我有更大的帮助,因为我仍然无法掌握。
  • @DavidC.Rankin 今天scanf(), tomorrow the world!!!!
  • 我要你的图片集:)
  • @Alagusankar - 拿子弹 1 - 如何解决? (检查退货)。 Bullet 2 - 使用 field-width 修饰符 请参阅scanf(3) - Linux manual page,Bullet 3 - 您请求匹配文字 's' 后面的字符集合而不是 '\n',Bullet 4 来自 3 , Bullet 5 - 说明 %[...] 本身就是一个完整的转换说明符,后面的 's' 必须与输入中的文字 's' 匹配(您的使用是多余的)。, Bullet 6 从 5 开始。(或者让生活更轻松,使用 fgets()
【解决方案2】:

您可以使用 scanf(“%s”, s) 将字符串作为 C 中的输入。但是,它只接受字符串,直到找到第一个空格。

为了将一行作为输入,可以使用 scanf("%[^\n]%*c", s);其中 s 定义为 char s[MAX_LEN] 其中 MAX_LEN 是 s 的最大大小。这里,[] 是扫描集字符。 ^\n 代表在没有遇到换行符之前接受输入。然后,使用这个 %*c,它读取换行符,这里使用的 * 表示这个换行符被丢弃。

注意:输入字符和字符串后,上述语句输入句子将不起作用。这是因为,在每一行的末尾,都有一个换行符 (\n)。所以,语句:scanf("%[^\n]%*c", s);将不起作用,因为最后一条语句将从前一行读取换行符。这可以通过多种方式处理,其中之一是:scanf("\n");在最后一条语句之前。

【讨论】:

    猜你喜欢
    • 2015-07-15
    • 2013-02-02
    • 2017-12-29
    • 2017-07-27
    • 2018-08-08
    • 1970-01-01
    • 1970-01-01
    • 2020-02-15
    • 1970-01-01
    相关资源
    最近更新 更多