Читаем Программирование полностью

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

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

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

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

vector 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[5], индекс которого ссылается за пределы вектора. Эта разновидность ошибок настолько широко известна, что даже получила несколько названий: ошибка занижения или завышения на единицу (off-by-obe error), ошибка диапазона (range error), так как индекс не принадлежит допустимому диапазону вектора, и ошибка пределов (bounds error), поскольку индекс выходит за пределы вектора.

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

vector v(5);

int x = v[5];

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

int main()

try {

  vector 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 даже не знает, частью какой программы может стать его код.

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

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных