如何一次一个单词而不是一行一行地消除错误输入

How to get rid of bad input one word at a time instead of one line at a time?

本文关键字:一行 错误 输入 何一次 一个 单词      更新时间:2023-10-16

我正在阅读"C++引物加/Stephen Prata"

这是这本书的代码

    while (!(cin >> golf[i])) {
        cin.clear();    // reset input
        while (cin.get() != 'n')
            continue;   // get rid of bad input
        cout << "Please enter a number: ";
    }

上面的代码很容易理解。

但这本书的上下文提到了

"…该程序在while循环中使用cin.get()从行的末尾读取剩余的输入。这可以消除坏的输入以及行上的其他任何内容。另一种方法是读取下一个空白,这样可以一次一个单词而不是一次一行地消除错误输入最后,程序告诉用户输入一个数字。"

我想知道另一种方法是什么?

我试图用不同的方式表达代码,但我知道这是不正确的。

    while (!(cin >> golf[i])) {
        cin.clear();    // resset input
        char word[20];
        while (cin >> word)
            continue;   // get rid of bad input
        cout << "Please enter a number: ";
    }

我该如何编写代码以读取下一个空白,这样可以一次一个单词而不是一次一行地消除错误输入?

谢谢你的阅读。

让我们从现有代码开始:

    while (cin.get() != 'n')
        continue;

这就是读到新行的内容。我们读取一个字符,将其与新行进行比较,如果不相等,我们读取另一个字符。因此,它读取字符,当它到达新行时停止读取。

如果我们想读取一个空格字符,我们只需更改比较的值:

    while (cin.get() != ' ')
        continue;

如果我们想在任何空白处停止阅读,我们可以使用一个函数来告诉我们一个字符是否为空白。这个函数看起来像这样:

bool is_white_space(char ch) { 
    return ch == ' ' || ch == 't' || ch == 'n' || ch == 'r' || ch == 'v';
}

但这是一个常见的任务,标准库已经有了isspace函数,所以我们不必编写自己的函数。我们只需要使用它:

while (!isspace(cin.get())
    continue;

就我个人而言,我至少会考虑将其单独放入一个函数中,并给它一个可读的名称,如skip_to_whitespace,这样我们的外循环看起来像:

void skip_to_space(std::istream &in) { 
    in.clear();
    while (!isspace(in.get()))
        continue;
}
// ...
while (!(cin >> golf[i])) {
    skip_to_space(cin);
    cout << "Please enter a number: ";
}

至少对我来说,这似乎使代码的意图更加明显——我们不必通读循环的内容来弄清楚它应该做什么——这从函数的名称中就很明显了。

不过,我还有最后一件事要改变。如果条件为false,则while循环通常不起作用。然而,这一个总是从输入中读取至少一个字符,无论该字符可能是什么。为了使这一事实更加明显,我更喜欢使用do循环,以正确反映循环总是至少执行一次的意图:

void skip_to_space(std::istream &in) { 
    in.clear();
    char ch;
    do {
        ch = in.get();
    } while (!isspace(ch));
}

现在很明显,cin.get()总是至少发生一次,并且一直发生,直到我们达到空白字符。

要抛出单词直到达到数字,请执行以下操作:

string word;
cout << "Please enter a number: ";
while(!(cin >> golf[i])){
    cin.clear();
    cin >> word;
    if(cin.rdbuf()->in_avail() == 1){
        cin.ignore(std::numeric_limits<std::streamsize>::max(), 'n');
        cout << "Please enter a number: ";
    }
}

抛出整行的一种方法是使用ignore

while (!(cin >> golf[i])) {
    cin.clear();    // resset input
    cin.ignore(numeric_limits<streamsize>::max(), 'n');   // get rid of bad input
    cout << "Please enter a number: ";
}