Программирование. Принципы и практика использования C++ Исправленное издание, стр. 320
const Message& m = *p; string s; if (find_from_addr(&m,s)) sender.insert(make_pair(s,&m)); } // Теперь перемещаемся по объекту класса multimap // и извлекаем темы сообщений, поступивших от John Doe: typedef multimap<string, const Message*>::const_iterator MCI; pair<MCI,MCI> pp = sender.equal_range("John Doe < [email protected]>"); for(MCI p = pp.first; p!=pp.second; ++p) cout << find_subject(p–>second) << '\n';}
multimapmultimap• создать ассоциативный массив;
• использовать ассоциативный массив.
Мы создаем объект класса
multimapinsert()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()Почему мы используем ссылку
mpfind_from_addr(p,s)Mess_iterMessageПочему мы сначала записали объекты класса
MessagemultimapMessagemap• Сначала мы создаем универсальную структуру, которую можно использовать для многих вещей.
• Затем используем ее в конкретном приложении.
Mail_filemultimapsenderAddressСоздание приложений по этапам (или слоям (layers), как их иногда называют) может значительно упростить проектирование, реализацию, документацию и эксплуатацию программ. Дело в том, что каждая часть приложения решает отдельную задачу и делает это вполне очевидным образом. С другой стороны, для того чтобы сделать все сразу, нужен большой ум. Очевидно, что извлечение информации и заголовков сообщений электронной почты — это детский пример приложения. Значение разделения задач, выделения модулей и поступательного наращивания приложения по мере увеличения масштаба приложения проявляется все более ярко.
Для того чтобы извлечь информацию, мы просто ищем все упоминания ключа "John Doe", используя функцию
equal_range()[first,second]equal_range()find_subject()typedef multimap<string, const Message*>::const_iterator MCI;pair<MCI,MCI> pp = sender.equal_range("John Doe");for (MCI p = pp.first; p!=pp.second; ++p) cout << find_subject(p–>second) << '\n';Перемещаясь по элементам объекта класса map, мы получаем последовательность пар (ключ,значение), в которых, как в любом другом объекте класса
pairstringkeyfirstMessagesecond23.4.1. Детали реализации
Очевидно, что мы должны реализовать используемые нами функции. Соблазнительно, конечно, сэкономить бумагу и спасти дерево, предоставив читателям самостоятельно решить эту задачу, но мы решили, что пример должен быть полным.
Конструктор класса
Mail_filelinesmMail_file::Mail_file(const string& n) // открывает файл с именем "n" // считывает строки из файла "n" в вектор lines // находит сообщения в векторе lines и помещает их в вектор m, // для простоты предполагая, что каждое сообщение заканчивается