【问题标题】:Is it a bad idea to clear the buffer using a macro in C?使用 C 中的宏清除缓冲区是一个坏主意吗?
【发布时间】:2014-11-22 13:20:10
【问题描述】:

我正在使用我创建的宏在 scanf 后清除缓冲区,但有人告诉我这不是一个好主意,因为“很多原因”。您能解释一下为什么以及如何清洁它吗?我知道使用 fflush(stdin) 是一个非常糟糕的主意,因为它没有被定义。

这是我使用的宏:

#define CLEAR_BUFFER do { c = getchar(); } while (c != '\n' && c != EOF);

另外,另一个问题:在“现实世界”中使用 scanf 吗?如果是,人们如何清理缓冲区?

谢谢

【问题讨论】:

  • 如果您在阅读某些内容后遇到空格或换行符问题,您可以在 %d%f 或类似名称之前放置一个空格以消除它们,例如scanf(" %d",x)
  • 对于用户输入,使用fgets() 获取数据并很好地处理行缓冲输入流。
  • @pmg 对于健壮的代码,fgets 也需要清理,因为该行可能超过缓冲区大小
  • @humodz "...在 %d..." 之前放一个空格 不需要"%d" 将使用可选的前导空格,即使格式中没有前面的 " "。这适用于除 "%c""%n""%[" 之外的所有 scanf() 说明符。
  • 什么是“bad”这个名字。我至少会称它为CLEAR_STDIN?

标签: c


【解决方案1】:

这个想法很好,但执行力可以改进:

#define CLEAR_BUFFER() do { int ch; while ( (ch = getchar()) != EOF && ch != '\n' ) {} } while (0)

您的版本没有声明c,可能会被错误地使用。

如果您不熟悉do...while(0)see here

写一个函数比这两个更好:

void clear_buffer(void)
{
    int ch; while ( (ch = getchar()) != EOF && ch != '\n' ) {} 
}

如果您有兴趣区分是否发生 EOL 或是否存在错误,您可以返回 bool(但调用代码可以检查 feof(stdin) || ferror(stdin) 以找出答案)。

在 C99 中,这可能是一个内联函数,尽管如果您在 C90 中并使其成为非内联函数,这并不是什么大问题。


对于问题的第二部分:我从不使用scanf,我按照我刚才描述的方式清理缓冲区。当然其他人可能会有所不同,这更多的是个人喜好问题。

【讨论】:

  • 我宁愿让clear_buffer()返回ch ...这样调用代码就可以轻松检测到EOF
  • 在获取所需输入后使用%*c 敲掉换行符是个坏主意吗?
  • 我更喜欢原来的 do while 方法,对我来说似乎更具可读性。
  • @KarolyHorvath 原版没有声明 c 所以无论如何它都需要一些工作
  • @MattMcNabb 如果此循环的目的是获取换行符或 EOF,我们不能在 scanf() 中使用%*c 和格式说明符吗?
猜你喜欢
  • 2010-12-06
  • 1970-01-01
  • 2016-08-18
  • 1970-01-01
  • 2020-04-11
  • 1970-01-01
  • 1970-01-01
  • 2012-11-19
  • 1970-01-01
相关资源
最近更新 更多