В отличие от карты, набор — это просто коллекция ключей. Набор полезен тогда, когда необходимо знать, имеется ли в нем значение. Например, банк мог бы определить набор bad_checks для хранения имен личностей, которые выписывали фальшивые чеки. Прежде чем принять чек, этот банк запросил бы набор bad_checks и убедился, есть ли в нем имя клиента.
mapКлассическим примером применения ассоциативного массива является программа подсчета слов:
//
map
string word;
while (cin >> word)
++word_count[word]; //
for (const auto &w : word_count) //
//
cout << w.first << " occurs " << w.second
<< ((w.second >1) ? " times" : " time") << endl;
Эта программа читает ввод и сообщает, сколько раз встречается каждое слово.
Подобно последовательным контейнерам, ассоциативные контейнеры являются шаблонами (см. раздел 3.3). Чтобы определить карту, следует указать типы ключа и значения. В этой программе карта хранит элементы, ключи которых имеют тип string, а значения — тип size_t (см. раздел 3.5.2). При индексации карты word_count строка используется как индекс, а возвращаемый счетчик типа size_t связан с этой строкой.
Цикл while читает слова со стандартного устройства ввода по одному за раз. Он использует каждое слово для индексирования карты word_count. Если слова еще нет в карте, оператор индексирования создает новый элемент, ключом которого будет слово, а значением 0. Независимо от того, должен ли быть создан элемент, его значение увеличивается.
Как только весь ввод прочитан, серийный оператор for (см. раздел 3.2.3) перебирает карту выводя каждое слово и соответствующий счетчик.
При получении элемента из карты возвращается объект типа pair (пара), рассматриваемого в разделе 11.2.3 (стр. 545). Если не вдаваться в подробности, то pair — это шаблон типа, который содержит две открытые переменные-члена по имени first (первый) и second (второй). У используемых картой пар член first является ключом, a second — соответствующим значением. Таким образом, оператор вывода должен отобразить каждое слово и связанный с ним счетчик.
Если бы эта программа была запущена для текста первого параграфа данного раздела, то вывод был бы таким:
Although occurs 1 time
Before occurs 1 time
an occurs 1 time
and occurs 1 time
...
setЛогичным усовершенствованием создаваемой программы будет игнорирование таких распространенных слов, как "the", "and", "or" и т.д. Для хранения игнорируемых слов будет использован набор, а подсчитываться будут только те слова, которые отсутствуют в этом наборе:
//
map
set
"the", "but", "and", "or", "an", "a"};
string word;
while (cin >> word)
// подсчитать только не исключенные слова
if (exclude.find(word) == exclude.end())
++word_count[word]; //
Подобно другим контейнерам, set является шаблоном. Чтобы определить набор, следует указать тип его элементов, которым в данном случае будет string. Подобно последовательным контейнерам, для элементов ассоциативного контейнера применима списочная инициализация (см. раздел 3.3.6). Набор exclude будет содержать 12 слов, которые следует игнорировать.
Важнейшее различие между этой программой и предыдущей в том, что перед подсчетом каждого слова оно проверяется на принадлежность к набору исключенных. Для этого используется оператор if:
//
if (exclude.find(word) == exclude.end())
Вызов функции find() возвращает итератор. Если заданный ключ находится в наборе, итератор указывает на него. Если элемент не найден, функция find() возвращает итератор на элемент после конца. В этой версии счетчик слов изменяется, только если слово не находится в наборе exclude.
Если запустить эту версию для того же ввода, что и прежде, вывод будет таким: