安全操作以清除C++中的空输入缓冲区

Safe operation to clear the empty input buffer in C++

本文关键字:输入 缓冲区 C++ 操作 清除 安全      更新时间:2023-10-16

我正在看这篇文章和其他一些帖子。如果在输入缓冲区已经为空时调用 ignore() 会发生什么?我在下面的代码中观察到,如果在缓冲区已经为空时调用 ignore(),它将不起作用并等待先输入某个字符。

int main(void)
{
char myStr[50];
cin.ignore (std::numeric_limits<std::streamsize>::max(),'n');
cout<<"Enter the Stringn";
cin>>myStr;
// After reading remove unwanted characters from the buffer
// so that next read is not affected
cin.ignore (std::numeric_limits<std::streamsize>::max(),'n');
}

Cin.clear() 在 ignore() 之后,如果缓冲区已经为空,它看起来会产生进一步的问题。我想在 cin() 之后清除缓冲区是安全的。但是,如果我不知道输入缓冲区的状态,即使它已经为空,我也清除了怎么办?我是否必须首先使用 cin.fail() 或类似的东西(如果有的话)检查输入缓冲区是否为空?

其次,cin 本身可能不安全,因为不允许使用空间。所以 getline() 是由一些 SO 帖子建议的,如此处给出的。但是getline()是否也需要清除输入缓冲区,或者它总是安全的?下面的代码是否可以正常工作(它现在可以工作,但现在确定它是否是安全代码)。

void getString(string& str)
{
do
{
cout<<"Enter the String: ";
getline(std::cin,str);
}  while (str.empty());
}

其他 SO 参考资料: 参考文献 3

分解main

int main(void)
{
char myStr[50];
cin.ignore (std::numeric_limits<std::streamsize>::max(),'n');

一个坏主意,但你已经注意到了。流中必须有一个换行符,否则您坐下来等待一个换行符。如果用户不希望出现这种行为,您可能会等待很长时间并让用户感到沮丧。那是一个糟糕的场景。

cout<<"Enter the Stringn";
cin>>myStr;

也是一个坏主意,但出于不同的原因。>>不知道它应该停止在 49 个字符以防止溢出myStr。坏事发生在第50个字符。

// After reading remove unwanted characters from the buffer
// so that next read is not affected
cin.ignore (std::numeric_limits<std::streamsize>::max(),'n');

这个是安全的。>>不会使用换行符或任何其他空格,为了使流从控制台移交数据,必须有人按 Enter 并提供换行符。

}

一般的经验法则是不要ignore,除非您有理由ignore,如果您有理由,请立即忽略。不要等到下一次流操作之前才ignore,否则如果这个操作是第一个怎么办?或者以前的操作没有留下任何东西可以ignore?。ignore在将您想要的内容ignore留在流中的操作之后。所以

std::string getfirstword()
{
std::string firstword;
if (std::cin >> firstword)
{
cin.ignore (std::numeric_limits<std::streamsize>::max(),'n');
return firstword;
}
return ""; // or perhaps
// throw std::runtime_error("There is no first word.");
// is more appropriate. Your call.
}

很好,但是

std::string getfirstword()
{
cin.ignore (std::numeric_limits<std::streamsize>::max(),'n');
std::string firstword;
if (std::cin >> firstword)
{
return firstword;
}
return "";
}

在所有圣洁的眼中是一种冒犯。别这样。

至于getline,它得到了一条线。所有这些都直到文件末尾或行尾,以先到者为准。它还会为您吃掉线路的尽头,因此您不必担心流浪的换行符稍后会刺痛您的醇厚。

如果你只想要部分行,你将不得不分解它。其典型用法类似于

std::string line;
if (std::getline(std::cin,line))
{
std::istringstream istr(line);
std::string firstword;
if (istr >> firstword)
{
// do something with firstword
}
else
{
// there is no firstword. Do something else.
}
}

getline读取所有内容,包括换行符。它不再在溪流中,所以我认为这是安全的。您不必担心垃圾在生产线末端徘徊。不过,您可能需要担心下一行。