Kniga-Online.club
» » » » Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп

Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп

Читать бесплатно Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп. Жанр: Программирование год 2004. Так же читаем полные версии (весь текст) онлайн без регистрации и SMS на сайте kniga-online.club или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.
Перейти на страницу:
class="code">  return length*width;

}

Иначе говоря, если аргументы правильные, то программа всегда возвращает площадь прямоугольника, а если нет, то выходим из функции area() с помощью оператора throw, надеясь найти ответ в одном из разделов catch. Bad_area — это новый тип, предназначенный исключительно для генерирования исключений в функции area(), так, чтобы один из разделов catch распознал его как исключение, сгенерированное функцией area(). Типы, определенные пользователями (классы и перечисления), обсуждаются в главе 9. Обозначение Bad_area() означает “Создать объект типа Bad_area”, а выражение throw Bad_area() означает “Создать объект типа Bad_area и передать его (throw) дальше”.

Теперь функцию можно написать так:

int main()

try {

  int x = –1;

  int y = 2;

  int z = 4;

  // ...

  int area1 = area(x,y);

  int area2 = framed_area(1,z);

  int area3 = framed_area(y,z);

  double ratio = area1/area3;

}

catch (Bad_area) {

  cout << "Ой! Неправильный аргумент функции area()n";

}

Во-первых, этот фрагмент программы обрабатывает все вызовы функции area() как вызов из модуля main(), так и два вызова из функции framed_area(). Во-вторых, обработка ошибки четко отделена от ее выявления: функция main() ничего не знает о том, какая функция выполнила инструкцию throw Bad_area(), а функция area() ничего не знает о том, какая функция (если такая существует) должна перехватывать исключения Bad_area, которые она генерирует. Это разделение особенно важно в крупных программах, написанных с помощью многочисленных библиотек. В таких программах ни один человек не может обработать ошибку, просто поместив некоторый код в нужное место, поскольку никто не может модифицировать код одновременно в приложении и во всех библиотеках.

5.6.2. Ошибки, связанные с диапазоном

Большинство реальных программ работает с наборами данных. Иначе говоря, они используют разнообразные таблицы, списки и другие структуры данных. В контексте языка С++ наборы данных часто называют контейнерами (containers). Наиболее часто используемым контейнером стандартной библиотеки является тип vector, введенный в разделе 4.6.

Объект типа vector хранит определенное количество элементов, которое можно узнать с помощью его функции-члена size(). Что произойдет, если мы попытаемся использовать элемент с индексом, не принадлежащим допустимому диапазону [0:v.size()]? Обычное обозначение [low:high] означает, что индексы могут принимать значения от low до high-1, т.е. включая нижнюю границу, но исключая верхнюю.

Прежде чем ответить на этот вопрос, необходимо ответить на другой: “Как это может быть?” Помимо всего прочего, известно, что индекс вектора v должен лежать в диапазоне [0:v.size()], поэтому достаточно просто убедиться в этом!

Легко сказать, но трудно сделать. Рассмотрим следующую вполне разумную программу:

vector<int> v; // вектор целых чисел

int i;

while (cin>>i) v.push_back(i);    // вводим значения в контейнер

for (int i = 0; i<=v.size(); ++i) // печатаем значения

  cout << "v[" << i <<"] == " << v[i] << endl;

Видите ошибку? Попытайтесь найти ее, прежде чем двигаться дальше. Эта довольно типичная ошибка. Мы часто ее делаем, особенно если программируем поздно ночью, когда устали. Ошибки, как правило, являются результатом спешки или усталости.

Мы использовали 0 и size(), чтобы попытаться гарантировать, что индекс i всегда будет находиться в допустимом диапазоне, когда мы обратимся к элементу v[i]. К сожалению, мы сделали ошибку. Посмотрите на цикл for: условие его завершения сформулировано как i<=v.size(), в то время как правильно было бы написать i<v.size(). В результате, прочитав пять чисел, мы попытаемся вывести шесть. Мы попытаемся обратиться к элементу v[5], индекс которого ссылается за пределы вектора. Эта разновидность ошибок настолько широко известна, что даже получила несколько названий: ошибка занижения или завышения на единицу (off-by-obe error), ошибка диапазона (range error), так как индекс не принадлежит допустимому диапазону вектора, и ошибка пределов (bounds error), поскольку индекс выходит за пределы вектора.

Эту ошибку можно спровоцировать намного проще.

vector<int> v(5);

int x = v[5];

Однако мы сомневаемся, что вы признаете такой пример реалистичным и заслуживающим внимания. Итак, что же произойдет на самом деле, если мы сделаем ошибку диапазона? Операция доступа по индексу в классе vector знает размер вектора, поэтому может проверить его (и действительно, делает это; см. разделы 4.6 и 19.4). Если проверка заканчивается неудачей, то операция доступа по индексу генерирует исключение типа out_of_range. Итак, если бы ошибочный код, приведенный выше, являлся частью какой-то программы, перехватывающей исключения, то мы получили бы соответствующее сообщение об ошибке.

int main()

try {

  vector<int> v; // вектор целых чисел

  int x;

  while (cin>>x) v.push_back(x);    // записываем значения

  for (int i = 0; i<=v.size(); ++i) // выводим значения

    cout << "v[" << i <<"] == " << v[i] << endl;

} catch (out_of_range) {

    cerr << "Ой! Ошибка диапазона n";

    return 1;

  } catch (...) { // перехват всех других исключений

   cerr << "Исключение: что-то не так n";

   return 2;

}

Обратите внимание на то, что ошибка диапазона на самом деле является частным случаем ошибки, связанной с аргументами, которую мы обсудили в разделе 5.5.2. Не доверяя себе, мы поручили проверку диапазона индексов вектора самой операции доступа по индексу. По очевидным причинам оператор доступа по индексу (vector::operator[]) сообщает об ошибке, генерируя исключение. Что еще может произойти? Оператор доступа по индексу не имеет представления о том, что бы мы хотели в этой ситуации делать. Автор класса vector даже не знает, частью какой программы может стать его код.

5.6.3. Неправильный ввод

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

Рассмотрим фрагмент кода, в котором вводится число с плавающей точкой.

Перейти на страницу:

Бьёрн Страуструп читать все книги автора по порядку

Бьёрн Страуструп - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки kniga-online.club.


Программирование. Принципы и практика использования C++ Исправленное издание отзывы

Отзывы читателей о книге Программирование. Принципы и практика использования C++ Исправленное издание, автор: Бьёрн Страуструп. Читайте комментарии и мнения людей о произведении.


Уважаемые читатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.

  • 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
  • 2. Просьба отказаться от оскорблений, угроз и запугиваний.
  • 3. Просьба отказаться от нецензурной лексики.
  • 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.

Надеемся на Ваше понимание и благоразумие. С уважением, администратор kniga-online.


Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*