如何清空cin缓冲区?

134

我该如何在C++中清空cin缓冲区?

14个回答

140

我更喜欢C++的尺寸限制,而不是C语言版本的:

// Ignore to the end of Stream
std::cin.ignore(std::numeric_limits<std::streamsize>::max())

// Ignore to the end of line
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n')

18
更重要的是,这些值可能不同!(streamsize 不一定是 int 类型) - Roger Pate
2
请问你能给一个示例,我们需要忽略到文件末尾的原因是,如果我使用 cin 并使用上面的第一条语句来刷新 cin 缓冲区,那么它会不断提示输入,直到我通过按下 ctrl+d 来输入 EOF - ajay
@ajay:不,这是你需要决定的事情。我只是在解释上面的代码会做什么。 - Martin York

112

可能:

std::cin.ignore(INT_MAX);

这将读取并忽略所有内容,直到EOF。(您还可以提供第二个参数,该参数是要读取的字符(例如:'\n'以忽略一行)。)

另外:在此之前,您可能希望执行std::cin.clear();以重置流状态。


11
在流操作其缓冲区之前清除它,而不是之后,这样可以使流处于良好状态。 - GManNickG
5
我想指出对于我的情况,我发现 '\n' 是必要的。否则,后续的 "cin >>" 将无法工作。 - Cardin
1
对于我来说,这个程序会一直停止,直到找到至少与参数相同数量的字符(微软编译器)。 - Nic
@Nic - 当然,这会告诉代码忽略所有字符,直到指定的数量。在主要示例中,它将忽略基本上直到 EOF(因为 INT_MAX 很大)。如帖子中所述,如果您只想忽略一行,您需要指定一个额外的参数 '\n',以告诉它您只想忽略到行末。 - Evan Teran
如果你这样做,下次调用getline(cin, input)时,你可以一整天按下一个字符再按Enter,它也不会通过。 - user3015682
因为C++文件流和C文件流不共享缓冲区。每个实现都使用略有不同的方法进行独立缓冲。 - Evan Teran

33
cin.clear();
fflush(stdin);

当我从控制台读取内容时,这是唯一有效的方法。在其他情况下,由于缺少 \n,它会无限期地读取,或者有些东西会留在缓冲区中。

编辑: 我发现之前的解决方案使情况变得更糟。然而,这个解决方案是有效的:

cin.getline(temp, STRLEN);
if (cin.fail()) {
    cin.clear();
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

1
是的,不要在stdin上使用fflush(或任何已打开以供读取的流),这是未定义的行为。 - WENDYN

18

我已经找到了两个解决方法。

第一个,也是最简单的方法,是使用std::getline(),例如:

std::getline(std::cin, yourString);

...这将在遇到换行符时丢弃输入流。要了解有关此函数的更多信息,请单击此处

另一个直接丢弃流的选项是这个...

#include <limits>
// Possibly some other code here
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');

祝你好运!


11
int i;
  cout << "Please enter an integer value: ";

  // cin >> i; leaves '\n' among possible other junk in the buffer. 
  // '\n' also happens to be the default delim character for getline() below.
  cin >> i; 
  if (cin.fail()) 
  {
    cout << "\ncin failed - substituting: i=1;\n\n";
    i = 1;
  }
  cin.clear(); cin.ignore(INT_MAX,'\n'); 

  cout << "The value you entered is: " << i << " and its double is " << i*2 << ".\n\n";

  string myString;
  cout << "What's your full name? (spaces inclded) \n";
  getline (cin, myString);
  cout << "\nHello '" << myString << "'.\n\n\n";

6
如何呢:
cin.ignore(cin.rdbuf()->in_avail());

3
streambuf的in_avail()函数不可靠,许多实现只会返回零。参见:https://connect.microsoft.com/VisualStudio/feedback/details/509337/vc-8-9-sstream-basic-streambuf-sputc-sputn-dont-increment-gcount,gnu的libc++也是类似情况。 - James Caccese

5
另一个可能的(手动)解决方案是:
cin.clear();
while (cin.get() != '\n') 
{
    continue;
}

我无法在CLion中使用fflush或cin.flush(),所以这很方便。


对我来说是一个无限循环。 - StarWind0
只有在行末时才有效,否则会产生无限循环。 - Bobul Mentol

4

最简单的方法:

cin.seekg(0,ios::end);
cin.clear();

它只是将cin指针定位在stdin流的末尾,而cin.clear()则清除所有错误标志,例如EOF标志。


4

我更喜欢:

cin.clear();
fflush(stdin);

有一种情况是cin.ignore不起作用,但我现在想不起来了。当我需要使用它时(与Mingw一起使用),已经过了一段时间。

然而,根据标准,fflush(stdin)是未定义的行为。 fflush()仅适用于输出流。 fflush(stdin )似乎只在Windows上按预期工作(至少与GCC和MS编译器一起使用)作为C标准的扩展链接1

因此,如果您使用它,您的代码将无法移植。

请参见链接2的[使用fflush(stdin)]。

另请参阅链接3以获取替代方法。


11
fflush(stdin);在C编程语言中是未定义行为,在7.18.5.2/2中明确说明。 - Cubbi
2
提供有效且可行的权宜之计加1分。有些人有工作,而另一些人则有标准。 - Mikhail
8
@Mikhail:你的工作应该包括编写符合标准的代码。我会确保将来避免使用你编写的任何东西。 - Ed S.

4

对我有用。我使用了带有getline()的for循环。

cin.ignore()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接