Как обращаться с неправильным вводом типа данных

В С++, как вы обрабатываете неправильные входы? Например, если программа запрашивает целое число, когда вы вводите символ, он должен иметь возможность что-то сделать, а затем цикл для повторения ввода, но цикл бесконечен, когда вы вводите символ, когда целое число необходимо, и наоборот.

Ответы

Ответ 1

Причина, по которой программа переходит в бесконечный цикл, связана с тем, что флаг std::cin bad input установлен из-за сбоя ввода. Дело в том, чтобы очистить этот флаг и отбросить плохой вход из входного буфера.

//executes loop if the input fails (e.g., no characters were read)
while (std::cout << "Enter a number" && !(std::cin >> num)) {
    std::cin.clear(); //clear bad input flag
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //discard input
    std::cout << "Invalid input; please re-enter.\n";
}

См. С++ FAQ для этого и другие примеры, включая добавление минимума и/или максимума в условие.

Другим способом было бы получить ввод как строку и преобразовать его в целое число с помощью std::stoi или какой-либо другой метод, который позволяет проверять преобразование.

Ответ 2

Верхний голосовой ответ хорошо охватывает решение.

В дополнение к этому ответу, это может помочь визуализировать, что происходит немного лучше:

int main()

    int input = 1;//set to 1 for illustrative purposes
    bool cinState = false;
    string test = "\0";
    while(input != -1){//enter -1 to exit
        cout << "Please input (a) character(s): ";//input a character here as a test
        cin >> input; //attempting to input a character to an int variable will cause cin to fail
        cout << "input: " << input << endl;//input has changed from 1 to 0
        cinState = cin;//cin is in bad state, returns false
        cout << "cinState: " << cinState << endl;
        cin.clear();//bad state flag cleared
        cinState = cin;//cin now returns true and will input to a variable
        cout << "cinState: " << cinState << endl;
        cout << "Please enter character(s): ";
        cin >> test;//remaining text in buffer is dumped here. cin will not pause if there is any text left in the buffer.
        cout << "test: " << test << endl;
    }
    return 0;    
}

Отбрасывание текста в буфере переменной не особенно полезно, однако помогает визуализировать, почему требуется cin.ignore().

Я также отметил изменение входной переменной, потому что, если вы используете переменную ввода в своем состоянии для цикла while или оператор switch, он может зайти в тупик или выполнить условие, которое вы выполняли Ожидание, которое может быть более запутанным для отладки.

Ответ 3

Проверьте вход, чтобы узнать, ожидает ли ваша программа. Если это не так, предупредите пользователя о том, что введенный им ввод является неприемлемым.

Ответ 4

Вы можете проверить это через значение ASCII, если значение ascii s между 65 t0 90 или 97 to 122 будет символом.