In the article "using the <map> library to create an associated container", we discussed the map associated container in the standard library. But that is only part of the map container. The standard library also defines a multimap container, which is similar to map, except that it allows duplicate keys. This attribute makes multimap more useful than expected: for example, a person with the same phone book can have more than two phone numbers, in the file system, you can map multiple symbolic links to the same physical file, or the DNS server can map several URLs to the same IP address. In these scenarios, you can:// Note: pseudo code Multimap <string, string> phonebook; Phonebook. insert ("Harry", "8225687"); // home phone number Phonebook. insert ("Harry", "555123123"); // phone number of the organization Phonebook. insert ("Harry", "2532532532"); // mobile phone number The ability to store duplicate keys in multimap greatly affects its interfaces and usage. So how do I create an associated container with a non-unique key? The answer is to use the multimap container defined in the <map> library. Raise Questions Unlike map, multimap can contain duplicate keys. This raises the question: how does the overload subscript operator return multiple correlated values with the same key? The following pseudo code is used as an example: string phone=phonebook["Harry]; The standard library designer solves this problem by removing the subscript operator from multimap. Therefore, you must use different methods to insert and obtain elements and handle errors. Insert Suppose you need to develop a DNS Background Program (that is, a service program in Windows), which maps IP addresses to matched URL strings. You know that in some cases, the same IP address will be associated with multiple URLs. All these URLs point to the same site. In this case, you should use multimap instead of map. For example: #include <map> #include <string> multimap <string, string> DNS_daemon; Use the insert () member function instead of the subscript operator to insert an element. Insert () has a pair type parameter. In "use <map> library to create associated containers", we demonstrate how to use the make_pair () helper function to complete this task. You can also use it as follows: DNS_daemon.insert(make_pair("213.108.96.7","cppzone.com")); In the preceding insert () call, "213.108.96.7" is the key, and "cppzone.com" is the associated value. The same key will be inserted later, with different associated values: DNS_daemon.insert(make_pair("213.108.96.7","cppluspluszone.com")); Therefore, dns_daemon contains two elements with the same key value. Note that values returned by multimap: insert () and MAP: insert () are different. typedef pair <const Key, T> value_type; iterator insert(const value_type&); // #1 multimap pair <iterator, bool> insert(const value_type&); // #2 map The multimap: insert () member function returns an iteration pointer to the newly inserted element, that is, iterator (multimap: insert () can always be successfully executed ). However, MAP: insert () returns pair <iterator, bool>. Here, the bool value indicates whether the insert operation is successful. Search for a single value Similar to map, multimap has two versions of the reloaded find () member function: iterator find(const key_type& k); const_iterator find(const key_type& k) const; Find (k) returns the iteration pointer pointing to the first pair that matches the key K, that is, when you want to check whether there is at least one value associated with the key, or this function is most useful when only the first matching is required. For example: typedef multimap <string, string> mmss; void func(const mmss & dns) { mmss::const_iterator cit=dns.find("213.108.96.7"); if (cit != dns.end()) cout <<"213.108.96.7 found" <<endl; else cout <<"not found" <<endl; } Process multiple associated values The count (k) member function returns the number of values associated with the given key. The following example shows how many values are associated with the key "213.108.96.7: cout<<dns.count("213.108.96.7") //output: 2 <<" elements associated"<<endl; To access multiple values in multimap, use the member functions of performance_range (), lower_bound (), and upper_bound: Performance_range (k): This function searches for all values associated with K. Returns the pair of the iteration pointer, marking the start and end ranges. The following example shows all values associated with the key "213.108.96.7: typedef multimap <string, string>::const_iterator CIT; typedef pair<CIT, CIT> Range; Range range=dns.equal_range("213.108.96.7"); for(CIT i=range.first; i!=range.second; ++i) cout << i->second << endl; //output: cpluspluszone.com // cppzone.com Lower_bound () and upper_bound (): lower_bound (k) Find the first value associated with the key K, and upper_bound (k) is to find the element whose first key value is greater than K. The following example uses upper_bound () to locate the first element whose key value is greater than "213.108.96.7. Generally, when the key is a string, there will be a Dictionary Compilation comparison: dns.insert(make_pair("219.108.96.70", "pythonzone.com")); CIT cit=dns.upper_bound("213.108.96.7"); if (cit!=dns.end()) //found anything? cout<<cit->second<<endl; //display: pythonzone.com If you want to display all the values, you can use the following loop: // Insert multiple values with the same key DNS. insert (make_pair ("219.108.96.70", "pythonzone.com ")); DNS. insert (make_pair ("219.108.96.70", "python-zone.com ")); // Obtain the iteration pointer of the first value CIT = DNS. upper_bound ("213.108.96.7 "); // Output: pythonzone.com, python-zone.com While (CIT! = DNS. End ()) { Cout <cit-> second <Endl; ++ Cit; } Conclusion Although map and multimap have the same interface, the important difference lies in repeated keys. Design and use should be treated differently. Note the nuances of the insert () member function in each container. |