C++标准库(第2版)第7章map的一个运行期指定排序规则的示例

it2025-04-01  9

《C++标准库(第2版)》【德】Nicolai M.Josuttis著,侯捷 译 这本书,第7.8.6的一个综合实例:运用Map、String并于运行期指定排序规则

该例子展现了以下技巧:

如何使用map,包括使用关联式数组(associative array)接口。如何撰写和使用函数对象(function object)。如何在运行期定义排序规则(sorting criterion)。如何在“大小写无关”的情况下比较字符串(string)。 #include <iostream> #include <iomanip> #include <map> #include <string> #include <algorithm> #include <cctype> using namespace std; class RuntimeStringCmp { public: // constants for the comparison criterion enum cmp_mode { normal, nocase }; private: // actual comparison mode const cmp_mode mode; // auxiliary function to compare case insensitive static bool nocase_compare(char c1, char c2) { return toupper(c1) < toupper(c2); } public: // constructor: initializes the comparison criterion RuntimeStringCmp(cmp_mode m = normal) : mode(m) { } // the comparison bool operator() (const string& s1, const string& s2) const { if (mode == normal) { return s1 < s2; } else { return lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), nocase_compare); //(1)会有困惑的地方 } } }; typedef map<string, string, RuntimeStringCmp> StringStringMap; // function that fills and prints such containers void fillAndPrint(StringStringMap& coll); int main() { // create a container with the default comparison criterion StringStringMap coll1; fillAndPrint(coll1); // create an object for case-insensitive comparisons RuntimeStringCmp ignorecase(RuntimeStringCmp::nocase); // create a container with the case-insensitive comparisons criterion StringStringMap coll2(ignorecase); //(2)会有困惑的地方 fillAndPrint(coll2); getchar(); return 0; } void fillAndPrint(StringStringMap& coll) { // fill insert elements in random order coll["Deutschland"] = "Germany"; coll["deutsch"] = "German"; coll["Haken"] = "snag"; coll["arbeiten"] = "work"; coll["Hund"] = "dog"; coll["gehen"] = "go"; coll["Unternehmen"] = "enterprise"; coll["unternehmen"] = "undertake"; coll["gehen"] = "walk"; coll["Bestatter"] = "undertaker"; // print elements StringStringMap::iterator pos; cout.setf(ios::left, ios::adjustfield); for (pos = coll.begin(); pos != coll.end(); ++pos) { cout << setw(15) << pos->first.c_str() << " " << pos->second << endl; } cout << endl; }

运行结果: 上面的代码中有两个地方可能会有困惑 (1)会有困惑地方

lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), nocase_compare); //(1)会有困惑的地方

nocase_compare这个函数是静态成员函数,如果这个nocase_compare函数是普通函数,也是可以的。 比如改成:

bool nocase_compare(char c1, char c2) { return toupper(c1) < toupper(c2); } class RuntimeStringCmp { public: // constants for the comparison criterion enum cmp_mode { normal, nocase }; private: // actual comparison mode const cmp_mode mode; // auxiliary function to compare case insensitive //static bool nocase_compare(char c1, char c2) //{ // return toupper(c1) < toupper(c2); //} public: // constructor: initializes the comparison criterion RuntimeStringCmp(cmp_mode m = normal) : mode(m) { } // the comparison bool operator() (const string& s1, const string& s2) const { if (mode == normal) { return s1 < s2; } else { return lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), nocase_compare); //会有困惑的地方 } } };

其余代码保持不变,一样可以编译通过,运行结果相同。

(1)会有困惑地方

typedef map<string, string, RuntimeStringCmp> StringStringMap; //中间省略 // create an object for case-insensitive comparisons RuntimeStringCmp ignorecase(RuntimeStringCmp::nocase); // create a container with the case-insensitive comparisons criterion StringStringMap coll2(ignorecase); //(2)会有困惑的地方

查文档: http://www.cplusplus.com/reference/map/map/map/

explicit map (const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type());

std::map有这样的一个构造函数,就能理解了,第二个参数alloc就让它用默认值,前面的comp,传入ignorecase这个对象,就能说通了。也就通过这里控制是大小写忽略进行key值的比较。

学习完本例,就能解决了下面的问题:

如何使map :: find操作不区分大小写?

最新回复(0)