Пока l oop пропускает cin.getline () для C -строки - PullRequest
0 голосов
/ 26 января 2020

Я хочу использовать некоторое время l oop, чтобы неоднократно запрашивать у пользователя строку ввода с помощью 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 содержит a, b, c, \0, а на следующем l oop он делает паузу для следующей строки ввода, как и ожидалось.

Если пользователь вводит abcd, то arr по-прежнему содержит a, b, c, \0, но при следующем l oop первый элемент a изменяется на \0 и программа никогда больше не делает паузу для следующей строки ввода. Он просто печатает «Пожалуйста, введите 3 символа:» снова и снова. Почему? Как я могу заставить его делать паузу каждый раз, независимо от ввода?

решено

Спасибо Олафу за указание на то, что мне нужно сбросить бит ошибки.

#include <iostream>
#include <limits>
using namespace std;
int main()
{
    const int N = 3;
    char arr[N + 1] = {'\0'};
    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');
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 26 января 2020

Это происходит потому, что установлена ​​failbit, см. std::basic_istream::getline

ведет себя как UnformattedInputFunction. После создания и проверки объекта sentry, извлекает символы из * this и сохраняет их в последовательных местах массива, на первый элемент которого указывает s, до тех пор, пока не произойдет любое из следующих событий ( проверено в показанном порядке ) :

  • во входной последовательности наступает конец условия файла (в этом случае выполняется settate (eofbit))
  • следующий доступный символ c является разделителем, как определено Черты: экв. (c, делим). Разделитель извлекается (в отличие от basic_istream :: get ()) и учитывается в gcount (), но не сохраняется.
  • извлечено количество символов-1 (в этом случае выполняется settate (failbit)).

Это означает, что когда пользователь вводит более N символов, разделитель равен , а не найдено и N+1-1 символов было извлечено.

0 голосов
/ 26 января 2020

Согласно документации , второй параметр, N + 1, должен включать нулевой терминатор '\0'. Таким образом, abcd ввод не является допустимым вводом, потому что getline() нужен размер 5 для хранения строки, а также '\0'.

...