У меня проблема, я изучаю исключения и видимо что-то не так понял.
int n;
try {
cout << "enter value: " << endl;
cin >> n;
}
catch (exception& ex) {
cerr << ex.what();
}
cout << n;
Вывод для любого символьного литерала: Вывод самого литерала и ноль.
Я хочу понять, если пользователь вводит неверный тип данных, могу ли я как-то обработать этот ввод исключением и сказать пользователю, что он вводит текст, а не число? Как я могу понять, где происходит исключение? Как с помощью обработки остановить выполнение программы, иначе программа продолжает выполнять инструкции...
Я ввел нечисловое значение и ожидал, что программа сообщит мне об этом. Я ожидал, что после этого программа перестанет выполняться.
также я попробовал этот код
cout << "enter value: " << endl;
cin >> n;
if (!cin) throw exception();
try {
cout << n;
}
catch (exception& ex) {
cerr << ex.what();
}
«Символовый литерал» — это то, что вы пишете в исходном коде: например, 'a'
. Предположительно, ввод, вызывающий проблемы, не является цифровым символом.
Примечание: после подсказки в этом нет необходимости. std::endl
и std::cout
связаны; экстрактор потока (std::cin
) сначала сбрасывает std::cin >> n
, поэтому приглашение будет отображаться без принудительного его выполнения.
Re: «ввод текста, а не числа» — весь ввод пользователя представляет собой текст, а не число. Проблема в том, что текст начинается с нецифрового символа, поэтому его нельзя преобразовать в число.
Обычный путь здесь не предполагает исключений. Просто повторяйте цикл, пока ввод не станет действительным: while (!std::cin >> n) { /* clean up and prompt for new input */ }
.
вам следует проверить наличие ошибок в коде внутри блока try.
на основе вашего кода (похоже, вы используете std и endl)
код будет:
try {
std::cout << "Enter value \n";
std::cin >> value;
if (std::cin.fail())
throw (/*what ever error you want*/);
/*
or
if (std::cin.fail())
throw std::invalid_argument("your error text");
*/
}
catch(const char *e){
std::cerr << "ERROR " << e << '\n';
std::cin.clear();
// send user to try for new input as you want
}
/*
catch(const std::invalid_argument &err)
{
std::cerr << err.what() << '\n';
}
*/
endl
немного медленное, поэтому использование '\n'
ускорит ваш код.Также рекомендуется не использовать исключения таким образом. В качестве упражнения это нормально, но в реальном коде исключения не следует использовать для обычного управления потоком данных. Они используются, когда код, обнаруживающий проблему, не может ее решить.
@PeteBecker Конечно, но поскольку ОП хочет использовать try-catch
, я написал правильную форму этого кода.
Незначительная деталь: throw (/*what ever error you want*/);
конфликтует с catch(const char *e)
. catch
слишком конкретен. Я рекомендую выполнить оба сопоставления, а это будет означать передачу указателя на c-строку.
Обычно потоки не имеют маски исключений, установленной по умолчанию. Но вы можете установить нужную маску вручную, чтобы включить срабатывание исключений (например, когда установлен failbit
), например так:
#include <iostream>
int main()
{
int n{};
try
{
std::cin.exceptions(std::ios_base::failbit);
std::cout << "Enter value:\n";
std::cin >> n;
std::cout << "Got " << n << '\n';
}
catch (const std::ios_base::failure& err)
{
std::cerr << "Caught " << err.what() << '\n';
}
}
Однако обратите внимание: если после допустимого числового значения во входных данных есть какой-то мусор, оператор >> просто извлечет это значение и остановится (без сбоя). Сбой произойдет только в том случае, если в начале нет допустимого числового значения (игнорируя пробелы).
Чтобы его можно было поймать,
throw
должен находиться внутриtry { }
. И нет,cin
обычно не выдает ошибку при недопустимом вводе, вместо этого он прекращает чтение и устанавливает для себя условие ошибки.