pair
sender.equal_range("John Doe ");
for(MCI p = pp.first; p!=pp.second; ++p)
cout << find_subject(p–>second) << '\n';
}
multimap
multimap
делает именно это (облегчая доступ к элементам с помощью одного и того же ключа). Очевидно (и типично), что наша задача распадается на две подзадачи:• создать ассоциативный массив;
• использовать ассоциативный массив.
Мы создаем объект класса multimap
insert
:for (Mess_iter p = mfile.begin; p!=mfile.end; ++p) {
const Message& m = *p;
string s;
if (find_from_addr(&m,s))
sender.insert(make_pair(s,&m));
}
В ассоциативный массив включаются пары (ключ, значение), созданные с помощью функции make_pair
find_from_addr
.Почему мы используем ссылку m
p
явно и не вызвать функцию так: find_from_addr(p,s)
? Потому что, даже если мы знаем, что итератор Mess_iter
ссылается на объект класса Message
, нет никакой гарантии, что он реализован как указатель.Почему мы сначала записали объекты класса Message
multimap
? Почему сразу не включить объекты класса Message
в ассоциативный массив класса map
? Причина носит простой и фундаментальный характер.• Сначала мы создаем универсальную структуру, которую можно использовать для многих вещей.
• Затем используем ее в конкретном приложении.
Mail_file
multimap
(многозначительно названный sender
) упорядочен по полю Address
. Большинство других приложений могут использовать другой критерий сортировки: по полям Return, Recipients, Copy-to fields, Subject fields, временным меткам и т.д.Создание приложений по этапам (или
Для того чтобы извлечь информацию, мы просто ищем все упоминания ключа "John Doe", используя функцию equal_range
[first,second]
, возвращаемой функцией equal_range
, извлекая темы сообщений с помощью функции find_subject
.typedef multimap
pair
for (MCI p = pp.first; p!=pp.second; ++p)
cout << find_subject(p–>second) << '\n';
Перемещаясь по элементам объекта класса map, мы получаем последовательность пар (ключ,значение), в которых, как в любом другом объекте класса pair
stringkey
) называется first
, а второй (в данном случае объект класса Message
) — second
(см. раздел 21.6).23.4.1. Детали реализации
Очевидно, что мы должны реализовать используемые нами функции. Соблазнительно, конечно, сэкономить бумагу и спасти дерево, предоставив читателям самостоятельно решить эту задачу, но мы решили, что пример должен быть полным.
Конструктор класса Mail_file
lines
и m
.Mail_file::Mail_file(const string& n)
// открывает файл с именем "n"
// считывает строки из файла "n" в вектор lines
// находит сообщения в векторе lines и помещает их в вектор m,
// для простоты предполагая, что каждое сообщение заканчивается