While 循环跳过 C 字符串的 cin.getline()

While loop skips cin.getline() for C-string

我想使用 while 循环重复询问用户使用 cin.getline() 的一行输入并将输入存储为 C 字符串。

#include <iostream>
int main()
{
    const int N = 3;
    char arr[N + 1] = {};
    while (true)
    {
        std::cout << "Please enter " << N << " characters: ";
        std::cin.getline(arr, N + 1, '\n');
    }
}

如果用户键入 abc,则 arr 包含 abc[=18=],然后在下一个正如预期的那样,循环它会在下一行输入时暂停。

如果用户键入 abcd,则 arr 仍包含 abc[=18=],但在next 循环第一个元素 a 更改为 [=18=] 并且程序再也不会为下一行输入暂停。它只是一遍又一遍地打印出 "Please enter 3 characters: " 。为什么?无论输入如何,我怎样才能让它每次都暂停?

已解决

感谢 Olaf 指出我需要重置故障位。

#include <iostream>
#include <limits>
using namespace std;
int main()
{
    const int N = 3;
    char arr[N + 1] = {'[=12=]'};
    while (true)
    {
        cout << "Please enter " << N << " characters: ";
        cin.getline(arr, N + 1, '\n');
        if (cin.fail())
        {
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
        }
    }
}

根据 documentation,第二个参数 N + 1 必须包含 '[=11=]' 空终止符。因此,abcd 输入不是有效输入,因为 getline() 需要 5 的大小来存储字符串以及 '[=11=]'.

发生这种情况,因为 failbit is set, see std::basic_istream::getline

Behaves as UnformattedInputFunction. After constructing and checking the sentry object, extracts characters from *this and stores them in successive locations of the array whose first element is pointed to by s, until any of the following occurs (tested in the order shown):

  • end of file condition occurs in the input sequence (in which case setstate(eofbit) is executed)
  • the next available character c is the delimiter, as determined by Traits::eq(c, delim). The delimiter is extracted (unlike basic_istream::get()) and counted towards gcount(), but is not stored.
  • count-1 characters have been extracted (in which case setstate(failbit) is executed).

这意味着,当用户输入超过N个字符时,分隔符找到并且N+1-1个字符已被提取。