Избегайте неправильного ввода данных пользователем (строка, в которой запрашивается целое число) - PullRequest
1 голос
/ 25 марта 2019

У меня есть бесконечный цикл while, где у пользователя запрашивается номер.

Моя проблема очень проста: если ввод является строкой, я хочу повторно запросить ввод у пользователя, выдав сообщение «Введите правильный выбор:».

Я искал, и похоже, что мне нужно проверить cin.fail(), затем позвонить cin.clear() и cin.ignore().

Вот мой код:

int main() {
    int choice;
    bool failed = false;
    while (true) {
        if (failed) cout << "Enter a valid choice: ";
        else cout << "Enter a number: ";
        cin >> choice;

        if (cin.fail()) {
            cin.clear();
            cin.ignore();
            failed = true;
        }
    }

    return 0;
}

Однако это не решает мою проблему. Конечно, он не печатается бесконечно, но для каждой буквы лишняя буква печатает еще одну "Enter a valid choice:"

Похоже, мне нужно звонить cin.ignore() за каждое дополнительное письмо.

Есть ли другой способ сделать это?

Ответы [ 2 ]

1 голос
/ 25 марта 2019

У вас есть бесконечный цикл, потому что вы не прерываете цикл, даже когда введен правильный ввод. Это то, что вы действительно хотите? Если это так, то по крайней мере вы не сбрасываете флаг failed в допустимом вводе.

Что еще более важно, когда вводится неверный ввод, вы не игнорируете все, что было введено, вы игнорируете только 1 символ за раз. Вот почему вы видите дополнительные подсказки.

Попробуйте вместо этого:

int main() {
    int choice;
    while (true) {
        cout << "Enter a number: ";
        while (!(cin >> choice)) {
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            cout << "Enter a valid choice: ";
        }
    }
    return 0;
}
0 голосов
/ 25 марта 2019

Причина, по которой он печатает так много раз, заключается в том, что вы очищаете только состояние cin, но не очищаете входной буфер. Вы можете сделать это несколькими способами: -

  1. Используйте fflush(stdin) для очистки входного буфера. Это метод C, который может быть выполнен путем включения заголовка cstdio.

  2. Используйте cin.ignore, чтобы игнорировать все символы в текущем потоке ввода. Вы можете сделать это, заменив строку cin.ignore(), которая игнорирует один символ, на этот код cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'), который игнорирует всю строку. Для этого вам нужен заголовок лимитов.

  3. Наконец, вы можете сделать то же самое с помощью простого цикла, подобного while (cin.get() != '\n'){continue;}, который игнорирует все символы до новой строки.

Также другой подход к той же проблеме состоит в том, чтобы принять ввод в виде строки и использовать функции strtol() или isdigit(), чтобы проверить, является ли ввод действительным.

Кстати, бесконечный цикл заключается в том, что вы не использовали оператор break для завершения цикла. Таким образом, вы можете избежать этого, добавив

if(!failed)
   break;

Также вам нужно изменить состояние Failed на входе каждого цикла, добавив

failed=false;

в начале тела цикла.

...