Определенный ввод с плавающей точкой ломает программу на C++

int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);

    int dlina;

    cout << "Введите длину действительного массива меньшую или равную 30: ";

    while (true) {
        cin >> dlina;
        if (dlina > 30 || dlina < 1){
            printf("Некорректное значение! Введите еще раз: ");
            }
        else break;
    }
}

Проблема в том, что если число до точки не соответствует условию, то оно ломает терминал и цикл продолжается бесконечно, например, число -2.73. Каким самым простым способом это можно исправить?


Ответы (2 шт):

Автор решения: Serge3leo

При ошибке формата, cin переходит в состояние ошибки, поэтому ваш цикл не завершается. Для "исправления", например, при чисто интерактивном использовании, можно попробовать так:

while (!(cin >> dlina) || dlina > 30 || dlina < 1) {
    if (cin.eof() || cin.bad()) {
        cerr << "Конец файла или ошибка В/В.\n";
        return -1;
    }
    cout << "Некорректное значение! Введите еще раз: ";
    cin.clear();
    // Пропускаем остаток строки (с некорректными символами,
    // или, возможно, только '\n', при нарушении границ)
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

Следует заметить, что при входной строке: "4.2", dlina считается, как 4, а ".2" останутся несчитаными в cin для последующих операций ввода.

P.S.

При использовании в общем виде, а не в main(), может быть удобно вместо if (cin.eof() || cin.bad())... вызвать до цикла cin.exceptions(~cin.failbit) - выбрасывать исключение std::ios_base::failure при любой ошибке, кроме ошибки формата.

→ Ссылка
Автор решения: CrazyElf

Всё элементарно - когда в потоке ввода встречается точка или любой другой символ, который не ожидается при вводе целого числа, то этот символ не забирается из потока, а остаётся в нём. То есть вы можете ввести даже просто одну точку вместо числа - и получить такое же поведение вашего кода. В dlina в этом случае попадает 0, срабатывает if с печатью ошибки, а некорректный символ остаётся в потоке, читается из него заново, опять печатается ошибка и т.д.

Введите длину действительного массива меньшую или равную 30: .
Некорректное значение! Введите еще раз: 
Некорректное значение! Введите еще раз: 
Некорректное значение! Введите еще раз: 
Некорректное значение! Введите еще раз:
...

(вывод будет без переводов строк, я их добавил для читаемости)

Про исправление есть другой ответ, я не знаю C++, советовать не возьмусь.

→ Ссылка