Используя оператор индексирования (раздел 3.2.3), можно выбрать указанный элемент. Подобно строкам, индексирование вектора начинаются с 0; индекс имеет тип size_type
соответствующего типа; и если вектор не константен, то в возвращенный оператором индексирования элемент можно осуществить запись. Кроме того, как было продемонстрировано в разделе 3.2.3, можно вычислить индекс и непосредственно обратиться к элементу в данной позиции.
Предположим, имеется набор оценок степеней в диапазоне от 0 до 100. Необходимо рассчитать, сколько оценок попадает в кластер по 10. Между нулем и 100 возможна 101 оценка. Эти оценки могут быть представлены 11 кластерами: 10 кластеров по 10 оценок каждый плюс один кластер для наивысшей оценки 100. Первый кластер подсчитывает оценки от 0 до 9, второй — от 10 до 19 и т.д. Заключительный кластер подсчитывает количество оценок 100.
Таким образом, если введены следующие оценки:
42 65 95 100 39 67 95 76 88 76 83 92 76 93
результат их кластеризации должен быть таким:
0 0 0 1 1 0 2 3 2 4 1
Он означает, что не было никаких оценок ниже 30, одна оценка в 30-х, одна в 40-х, ни одной в 50-х, две в 60-х, три в 70-х, две в 80-х, четыре в 90-х и одна оценка 100.
Используем для содержания счетчиков каждого кластера вектор с 11 элементами. Индекс кластера для данной оценки можно определить делением этой оценки на 10. При делении двух целых чисел получается целое число, дробная часть которого усекается. Например, 42/10=4, 65/10=6, а 100/10=10.
Как только индекс кластера будет вычислен, его можно использовать для индексирования вектора и доступа к счетчику, значение которого необходимо увеличить.
//
//
vector
unsigned grade;
while (cin >> grade) { //
if (grade <= 100) //
++scores[grade/10]; //
Код начинается с определения вектора для хранения счетчиков кластеров. В данном случае все элементы должны иметь одинаковое значение, поэтому резервируем 11 элементов, каждый из которых инициализируем значением 0
. Условие цикла while
читает оценки. В цикле проверяется допустимость значения прочитанной оценки (т.е. оно меньше или равно 100). Если оценка допустима, то увеличиваем соответствующий счетчик.
Оператор, осуществляющий приращение, является хорошим примером краткости кода С++:
++scores[grade/10]; //
Это выражение эквивалентно следующему:
auto ind = grade/10; //
scores[ind] = scores[ind] + 1; //
Индекс ячейки вычисляется делением значения переменной grade
на 10. Полученный результат используется для индексирования вектора scores
, что обеспечивает доступ к соответствующему счетчику для этой оценки. Увеличение значения этого элемента означает принадлежность текущей оценки данному диапазону.
Как уже упоминалось, при использовании индексирования следует позаботиться о том, чтобы индексы оставались в диапазоне допустимых значений (см. раздел 3.2.3). В этой программе проверка допустимости подразумевает принадлежность оценки к диапазону 0-100
. Таким образом, можно использовать индексы от 0
до 10
. Они расположены в пределах от 0
до scores.size() - 1
.
Новички в С++ иногда полагают, что индексирование вектора позволяет добавлять в него элементы, но это не так. Следующий код намеревается добавить десять элементов в вектор ivec
:
vector
for (decltype(ivec.size()) ix = 0; ix != 10; ++ix)
ivec[ix] = ix; //
Причина ошибки — вектор ivec
пуст; в нем нет никаких элементов для индексирования! Как уже упоминалось, правильный цикл использовал бы функцию push_back()
:
for (decltype(ivec.size()) ix = 0; ix != 10; ++ix)
ivec.push_back(ix); //