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

时间:2018-03-13 01:08:51

标签: c++ inputstream

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

int main(void)
{
    char myStr[50];
    cin.ignore (std::numeric_limits<std::streamsize>::max(),'\n');
    cout<<"Enter the String\n";
    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本身可能不安全,因为不允许空间。因此,某些SO帖子建议使用getline()给出here。但getline()是否也需要清除输入缓冲区或者总是安全吗?以下代码是否正常运行(现在可以使用,但现在确定它是否是安全代码)。

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

其他SO参考: Ref 3

1 个答案:

答案 0 :(得分:1)

分解main

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

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

    cout<<"Enter the String\n";
    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');

这个是安全的。 >>不会消耗换行符或任何其他空格,并且为了让流从控制台移交数据,必须有人输入并提供换行符。

}

一般的经验法则是ignore,除非你有理由ignore,如果你有理由,请立即忽略。不要等到下一个流操作到ignore之前,如果这个操作是第一个的话会导致什么?或者之前的操作没有给ignore留下任何东西?在您在流中留下您想要的ignore d的操作之后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读取所有内容,包括换行符。它不再在流中,所以我认为这是安全的。你不必担心垃圾在线路末端徘徊。不过,您可能不得不担心下一行。