#include <iostream>
#include <ctime>
#include <conio.h>
#include <string>
#define NOMINMAX
#include <limits>
#include <windows.h>
using namespace std;
void delay(double delaySec) {
clock_t delayClock = delaySec * CLOCKS_PER_SEC;
clock_t start = clock();
while (clock() - start < delayClock);
}
int main() {
setlocale(LC_ALL, "");
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
char ch;
double delaySec;
string phrase;
cin.exceptions(istream::failbit | istream::badbit);
do {
cout << "Введите время задержки в секундах: ";
try {
cin >> delaySec;
}
catch (istream::failure exp) {
cout << "Введите число!\n";
cin >> delaySec;
}
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Введите фразу: ";
getline(cin, phrase);
delay(delaySec);
cout << "Фраза: " << phrase << endl;
} while (delaySec != 0);
_getch();
return 0;
}
Если ввести не число, то выводится строка "Введите число", а потом выбрасывается исключение в строке cin >> delaySec в блоке catch:
Возникло необработанное исключение по адресу 0x74EAAA12 в Delay2.exe: исключение Microsoft C++: std::ios_base::failure по адресу памяти 0x005BEB14
Почему это происходит и как это исправить?
Разумеется, выбрасывается.
Во-первых, когда в процессе первого cin >> delaySec возникла ошибка и в потоке cin выставился флаг failbit, сам по себе этот флаг сбрасываться не будет. Поток cin переходит в перманентное ошибочное состояние. Вывести его из этого состояния, т.е. очистить флаги ошибок, можете только вы явным образом, например через вызов cin.clear().
Если поток находится в режиме выбрасывания исключений по каким-то флагам (как в вашем примере), то пока эти флаги не сброшены, все попытки чтения из данного потока будут мгновенно выбрасывать исключения, независимо от того, правильные данные вы подадите на вход или неправильные.
Вы флаг failbit нигде не сбрасываете. Поэтому в вашем случае второй cin >> delaySec не будет даже пытаться ничего читать из потока, а вместо этого сразу же снова выбросит fail-исключение, которые вы не ловите. Его вы и видите.
Во-вторых, даже если вы сделаете cin.clear(), вам все равно еще нужно убрать из входного потока ошибочные входные данные. Если вы этого не сделаете, то вторая попытка cin >> delaySec будет пытаться читать все тот же неправильный вход. В результате опять произойдет та же самая ошибка и выбросится то же самое исключение.
Я вижу, вы вставили в код чистку буфера от неправильного ввода
cin.ignore(numeric_limits<streamsize>::max(), '\n');
но попытку повторного чтения cin >> delaySec вы делаете еще до чистки буфера. Должно быть наоборот: чистить буфер нужно до повторной попытки чтения. (А cin.clear() нужно сделать до cin.ignore().)
Продвижение своими сайтами как стратегия роста и независимости