Программирование >>  Операторы преобразования типа 

1 ... 184 185 186 [ 187 ] 188 189 190 ... 239


virtual const char* whatO const:

К сожалению, стандарт не требует, чтобы объект исключения содержал какую-либо информацию об ошибочном потоке данных или о типе ошибки. Существует единственный переносимый способ получения информации об ошибке - сообщение, возвращаемое функцией what(). Впрочем, переносим только вызов what(), но не возвращаемая строка. Если требуется дополнительная информация, программист должен сам заботиться о ее получении.

Из этого поведения следует, что обработка исключений в большей степени ориентируется на непредвиденные ситуации. Собственно, поэтому она называется обработкой исключений, а не обработкой ошибок. Ожидаемые ошибки (например, ошибки форматирования при вводе данных пользователем) считаются нормальными , а для их обработки лучше использовать флаги состояния.

Основная область применения потоковых исключений - чтение предварительно отформатированных данных (например, автоматически сгенерированных файлов). Но даже в этом случае при обработке исключений возникают проблемы. Например, если данные читаются до конца файла, вы не сможете генерировать исключения ошибок без того, чтобы не получить исключение конца файла. Дело в том, что при обнаружении конца файла также устанавливается бит failbit (признак неудачи при чтении объекта). Чтобы отличить конец файла от ошибки ввода, придется дополнительно проверить состояние потока данных.

Следующий пример показывает, как зто делается. Функция readAndProcessSuna читает вещественные числа из потока данных до тех пор, пока не достигнут конец файла. Затем возвращается сумма прочитанных вещественных чисел:

io/sumla.cpp #1nclude <lstream>

namespace MyLib {

double readAndProcessSum [std::1stream& strm)

using std::ios: double value, sum;

Сохранение текущего состояния флагов исключений ios::iostate oldExceptions = strm.exceptlonsO:

/* Выдача исключений при установке флагов failbit и badbit

* - ВНИМАНИЕ: флаг failbit также устанавливается

* при достижении конца файла */

strm.exceptions Cios::failbit ios::badbit): try {

/* Пока поток находится в нормальном состоянии * - прочитать Значение и прибавить его к сумме */



sum = 0:

while (strm value) { sum += value:

catch (...) {

/* Если исключение произошло не из-за достижения конца файла.

* - восстановить старую маску исключений

* - перезапустить исключение */

1f (Istrm.eofO) {

strm.exceptions(oldExceptions): Восстановление маски throw: Перезапуск исключения

Восстановление старой маски исключений strm.exceptions (oldExceptlons):

Возврат суммы return sum:

Сначала функция сохраняет состояние маски исключений в переменной oldExceptions, чтобы восстановить ее позднее. Затем поток данных настраивается на выдачу исключений при требуемых условиях. Функция читает значения в цикле и суммирует их до тех пор, пока поток данных остается в нормальном состоянии. При достижении конца файла состояние потока данных перестает быть нормальным, и он генерирует исключение (хотя для флага eofbit исключение не генерировалось). Дело в том, что конец файла обнаруживается при неудачной тюпытке чтения новых данных, которая также устанавливает флаг failbit. Чтобы избежать выдачи исключения при достижении конца файла, мы организуем локальный перехват исключения и проверяем состояние потока данных функцией eof(). Исключение передается дальше только в том случае, если eof() возвращает false.

Следует помнить, что восстановление исходной маски исключений также может привести к выдаче исключений. Функция exceptions() генерирует исключение в том случае, если соответствующий флаг уже установлен для потока данных. Поэтому если поток данных генерировал исключения для флага eofbit, failbit или badbit при входе в функцию, эти исключения также будут переданы вызывающей стороне.

Ниже приведен простой пример вызова этой функции из main().

io/summaln.cpp #lnclude <iostream> #include <cstdl1b>

namespace MyLib {

double readAndProcessSum (std;:lstream&):



int mainO {

using namespace std; double sum;

try {

sum = MyLib;:readAndProcessSum(c1n);

catch (const los: :fa11ureat error) {

cerr I/O exception: error.what() endl; return EXITJAILURE;

catch (const exceptional error) {

cerr standard exception: error.whatO endl; return EXITJAILURE;

catch (...) {

cerr unknown exception endl; return EXIT FAILURE;

Вывод суммы

cout sum: sum endl;

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

io/sum2a.cpp #include <1stream>

namespace MyLib {

double readAndProcessSum (std::1stream& strm)

double value, sum;

/* Пока поток остается в нормальном состоянии * - прочитать очередное значение и прибавить его к сумме */

sum = 0;

while (strm value) { sum += value;

if Clstrm.eofO) { throw std::ios:ifailure

( input error in readAndProcessSumO );



1 ... 184 185 186 [ 187 ] 188 189 190 ... 239

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика