C++ STL 标准模板库提供了丰富的容器和算法,这些模板可以灵活组合使用,以满足不同场景下的需求。本章内容将对前面学习的知识进行总结,并重点讲解如何灵活使用STL中的vector和map容器,以及如何结合不同的算法进行组合。
通过灵活组合使用这些容器和算法,能够满足不同场景下的需求,实现高效的数据处理和操作。STL的设计思想是将数据结构和算法进行分离,使得开发者能够更加专注于解决问题,提高了代码的可读性和可维护性。因此,掌握STL的使用技巧对于C++程序员来说是非常重要的。
11.1 字典拆分为列表 此代码创建了一个std::map
容器,将一些测试数据插入到容器中,然后通过迭代器遍历该容器,并将key
和value
分别插入到vector
容器中,形成两个列表。
最后,分别将这两个列表打印出来。该代码的核心功能是将一个std::map
容器转换成两个vector
容器,同时输出两个vector
容器的内容,以此实现了std::map
的分离操作。
功能概述:将map
字典拆分为vect_key
和vect_value
两个Vector
列表
#include <iostream> #include <string> #include <map> #include <vector> using namespace std ; int main (int argc, char *argv[]) { std ::map <long , std ::string > map ; map .insert(std ::pair <long , std ::string >(1001 , "administrator" )); map .insert(std ::pair <long , std ::string >(1002 , "root" )); map .insert(std ::pair <long , std ::string >(1003 , "lyshark" )); std ::vector <long > vect_key; std ::vector <std ::string > vect_value; for (std ::map <long , std ::string >::iterator it = map .begin(); it != map .end(); it++) { vect_key.push_back(it->first); vect_value.push_back(it->second); } for (int x = 0 ; x < vect_key.size(); x++) std ::cout << "Key: " << vect_key[x] << std ::endl ; for (int x = 0 ; x < vect_value.size(); x++) std ::cout << "Value: " << vect_value[x] << std ::endl ; std ::system("pause" ); return 0 ; }
11.2 列表合并为字典 该代码创建了两个std::vector
容器,分别包含一些测试数据,并将这两个容器的元素通过循环方式逐一插入到一个std::map
容器中。最后,通过迭代器输出std::map
容器中所有的键值对。
该代码的核心功能是将两个std::vector
容器的元素分别对应地插入到一个std::map
容器中,并将最终的结果进行打印输出。
功能概述:将两个列表vect_key
和vect_value
通过循环合并为一个std::map
字典
#include <iostream> #include <string> #include <map> #include <vector> using namespace std ; int main (int argc, char *argv[]) { std ::vector <long > vect_key; std ::vector <std ::string > vect_value; vect_key.push_back(1001 ); vect_key.push_back(1002 ); vect_key.push_back(1003 ); vect_value.push_back("administrator" ); vect_value.push_back("root" ); vect_value.push_back("lyshark" ); std ::map <long , std ::string > map ; if (vect_key.size() == vect_value.size()) { for (int x = 0 ; x < vect_key.size(); x++) { map .insert(std ::pair <long , std ::string >(vect_key[x], vect_value[x])); } } for (std ::map <long , std ::string >::iterator it = map .begin(); it != map .end(); it++) { std ::cout << "Key: " << it->first << " | Value: " << it->second << std ::endl ; } std ::system("pause" ); return 0 ; }
11.3 根据字典键降序排序 该代码创建了一个std::map
容器,其中std::string
是key
,int
是value
。通过指定greater<string>
进行降序排列。该程序接着给容器对象添加多个键值对,其中包括使用insert()
函数和数组索引语法添加键值对。
最后,该程序使用迭代器循环遍历map
容器,将所有键值对按照key
的降序依次输出。该代码的核心功能是创建一个带有某种关键字类型的std::map
容器,并实现基本的添加数据和遍历数据的操作。
提示:MAP字典第三个参数不指定则按照升序排列,如果指定了greater<string>
则会按照降序排列
#include <iostream> #include <functional> #include <string> #include <map> using namespace std ; int main (int argc, char *argv[]) { std ::map <std ::string , int , greater<string >> map ; std ::map <std ::string , int , greater<string >>::iterator iter; map ["aa" ] = 90 ; map ["bbb" ] = 95 ; map ["cccc" ] = 100 ; map .insert(map <string , int >::value_type("ddddd" , 88 )); for (iter = map .begin(); iter != map .end(); iter++) { std ::cout << "key: " << iter->first << " Value: " << iter->second << std ::endl ; } std ::system("pause" ); return 0 ; }
11.4 根据字典键长度排序 该段代码创建了一个std::map
容器,其中key
是std::string
类型value
是int
类型。为实现按照key
长度进行排序,需要额外定义一个key_string_cmp
的结构体,该结构体要重载()
运算符以实现比较大小的功能。
接着,程序添加多个字符串类型的键值对到map
容器中,其中包括使用数组索引语法以及使用insert()
函数添加键值对。最后,程序使用迭代器循环输出map
容器的所有键值对,注意此时输出的键值对已经按照key
长度排好序了。
该代码的核心功能是创建一个针对字符串类型key
的std::map
容器,并按照key
长度进行排序,然后实现基本的添加数据和输出数据的功能。其中自定义排序需要我们定义key_string_cmp
排序结构,并将其传递到map
字典的第三个参数上即可。
#include <iostream> #include <string> #include <map> using namespace std ; struct key_string_cmp { bool operator () (const string & x, const string & y) { return x.length() < y.length(); } }; int main (int argc, char *argv[]) { std ::map <std ::string , int , key_string_cmp > string_map; std ::map <std ::string , int , key_string_cmp >::iterator string_iter; string_map["aaaa" ] = 90 ; string_map["bb" ] = 95 ; string_map["ccccc" ] = 100 ; string_map["d" ] = 24 ; for (string_iter = string_map.begin(); string_iter != string_map.end(); string_iter++) { std ::cout << "key: " << string_iter->first << " Value: " << string_iter->second << std ::endl ; } std ::system("pause" ); return 0 ; }
11.5 根据字典值排序 该代码创建了一个std::map
容器,其中key
是std::string
类型value
是int
类型。程序使用数组索引语法添加多个键值对。接着,该程序将map
容器中的数据取出来,放入到vector
容器中,实现了将std::map
转换为std::vector
的功能。
接下来,程序使用sort()
函数对转换为vector
结构的序列进行排序,此处使用的是value_cmp
结构体对value
进行排序。最后,该程序输出排序后的vector
容器的内容,此处输出的是key
和value
,且是按照value
从小到大的顺序输出。
该代码的核心功能是将一个std::map
容器转换为std::vector
容器,并按照某种规则对该vector
进行排序,以此实现对std::map
中数据的排序功能。
#include <iostream> #include <algorithm> #include <string> #include <vector> #include <map> using namespace std ; typedef pair <string , int > PAIR;struct value_cmp { bool operator () (const PAIR& P1, const PAIR& P2) { return P1.second < P2.second; } }; int main (int argc, char *argv[]) { std ::map <std ::string , int > map ; std ::map <std ::string , int >::iterator iter; map ["admin" ] = 90 ; map ["root" ] = 95 ; map ["lyshark" ] = 100 ; vector <PAIR>vect; for (iter = map .begin(); iter != map .end(); iter++) { vect.push_back(*iter); } sort(vect.begin(), vect.end(), value_cmp()); for (int x = 0 ; x < vect.size(); x++) { std ::cout << "输出Key: " << vect[x].first << std ::endl ; std ::cout << "输出Value: " << vect[x].second << std ::endl ; } std ::system("pause" ); return 0 ; }
11.6 根据字典键返回值 该代码创建了一个std::map
容器,其中key
是std::string
类型,value
是int
类型。程序使用数组索引语法添加多个键值对。
该程序实现了两种查找功能:
非函数版寻找:使用find()
函数根据key
查找相应的value
,如果查找到就输出值
在函数版寻找:使用get_value()
函数根据key
查找相应的value
,并返回该值,如果找不到则返回0
最后,该程序输出找到的value
。需要注意的是,两种方式都可以寻找相应的值。
该代码的核心功能是实现根据key
在std::map
容器中查找对应的值并输出结果。其中,采用了两种查找方式,一种是使用map
自带的find()
函数,另一种是通过定义一个函数实现的查找功能。
#include <iostream> #include <functional> #include <string> #include <map> using namespace std ; int get_value (std ::map <std ::string ,int > ptr, std ::string key) { std ::map <std ::string , int >::iterator iter; iter = ptr.find(key); if (iter != ptr.end()) { return iter->second; } return 0 ; } int main (int argc, char *argv[]) { std ::map <std ::string , int > map ; std ::map <std ::string , int >::iterator iter; map ["admin" ] = 90 ; map ["root" ] = 95 ; map ["lyshark" ] = 100 ; iter = map .find("lyshark" ); if (iter != map .end()) { std ::cout << "找到数值: " << iter->second << std ::endl ; } int ref_value = get_value(map , "root" ); std ::cout << "找到数值: " << ref_value << std ::endl ; std ::system("pause" ); return 0 ; }
11.7 根据字典值寻找键 该段代码创建了一个std::map
容器,其中key
是int
类型value
是std::string
类型。程序使用insert()
函数向map
容器中添加了多个元素。
该程序实现了两种查找功能:未封装的查找与封装函数版查找。在未封装的查找中,使用find_if()
函数根据value
完成查找;在封装函数版查找中,通过定义一个类map_value_finder
实现find_if()
函数。
最后,该程序输出找到的key
和value
。需要注意的是,两种方式都可以寻找相应的key
和value
。
该代码的核心功能是实现根据value
在std::map
容器中查找相应的key
和value
,并输出结果。其中,采用了两种查找方式,一种是使用find_if()
函数,另一种是通过定义一个类封装实现的查找功能。
#include <iostream> #include <vector> #include <map> #include <string> #include <algorithm> using namespace std ; class map_value_finder { public: map_value_finder(const std ::string &cmp_string) :m_s_cmp_string(cmp_string){} bool operator () (const std ::map <int , std ::string >::value_type &pair ) { return pair .second == m_s_cmp_string; } private: const std ::string &m_s_cmp_string; }; std ::pair < int , std ::string > get_item(std ::map <int ,std ::string > ptr, std ::string value){ std ::map < int , std ::string >::iterator it = ptr.end(); it = std ::find_if(ptr.begin(), ptr.end(), map_value_finder(value)); std ::pair < int , std ::string > ref_pair; if (it == ptr.end()) { ref_pair = std ::make_pair (0 , "None" ); return ref_pair; } else { ref_pair = std ::make_pair (it->first, it->second); return ref_pair; } } int main (int argc,char * argv[]) { std ::map <int , std ::string > map ; map .insert(std ::make_pair (10 , "china" )); map .insert(std ::make_pair (20 , "usa" )); map .insert(std ::make_pair (30 , "english" )); map .insert(std ::make_pair (40 , "hongkong" )); std ::map <int , std ::string >::iterator it = map .end(); it = std ::find_if(map .begin(), map .end(), map_value_finder("usa" )); if (it == map .end()) { std ::cout << "没找到.." << std ::endl ; } else { std ::cout << "找到的Key: " << it->first << " 找到的Value: " << it->second.c_str() << std ::endl ; } std ::pair <int , std ::string > ref = get_item(map , "english" ); std ::cout << "找到的Key: " << ref.first << " 找到的Value: " << ref.second << std ::endl ; std ::system("pause" ); return 0 ; }
11.8 寻找列表中相同元素 这段代码演示了两种查找算法find()
和find_first_of()
,实现了寻找两个列表中第一次出现在第二个容器中的元素。
第一种查找算法,使用find()
函数在vector
容器中查找特定元素,如果查找成功,则输出元素在容器中的位置(下标)。注意,该函数仅查找序列中的第一个符合条件的元素。
第二种查找算法,使用find_first_of()
函数在两个vector
容器之间查找相同元素,如果查找成功,则输出该元素及其位置。注意,该函数查找的是两个序列中第一个相同的元素,而不是整个序列中相同的元素。
此外,该程序还定义了一个函数test_find_if()
,用于在vector
容器中查找满足特定条件的元素,如果查找成功,则输出该元素及其位置(下标)。
#include <iostream> #include <vector> #include <map> #include <string> #include <algorithm> using namespace std ; bool MyFunction (int x) { if (x >= 9 ) return 1 ; else return 0 ; } void test_find_if (vector <int > ptr) { vector <int >::iterator iter; iter = find_if(ptr.begin(), ptr.end(), MyFunction); if (iter != ptr.end()) { cout << "满足条件的数: " << *iter << " 下标: " << iter - ptr.begin() << endl ; } } void test_find_first_of (std ::vector <int > VectA,std ::vector <int > VectB) { vector <int >::iterator iter; iter = find_first_of(VectA.begin(), VectA.end(), VectB.begin(), VectB.end()); if (iter != VectA.end() || iter != VectB.end()) { cout << "第一次出现在第二个容器中的元素为: " << *iter << " 下标: " << iter - VectA.begin() << endl ; } else { cout << "两个容器没有相同元素" << endl ; } } int main (int argc,char * argv[]) { std ::vector <int > vect = { 1 , 5 , 6 , 7 , 8 , 9 , 0 , 3 , 2 , 1 }; std ::vector <int >::iterator iter; iter = find(vect.begin(), vect.end(), 7 ); if (iter != vect.end()) { std ::cout << "找到元素下标: " << distance(vect.begin(), iter) << std ::endl ; } test_find_if(vect); std ::vector <int > VectA = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 }; std ::vector <int > VectB = { 5 , 6 , 7 , 8 , 9 , 4 , 32 , 6 , 8 , 9 }; test_find_first_of(VectA, VectB); std ::system("pause" ); return 0 ; }
11.9 查找列表中的交集 这段代码实现了一个函数get_vect_value_list()
,可以查找两个vector
容器中相同的元素,并将这些元素放入一个新的vector
容器中并返回。在具体实现中,使用了STL中的find()
函数来查找相同的元素,并通过push_back()
函数将查找到的元素添加到新的vector
容器中。
在主函数中,定义两个vector
容器VectA
和VectB
,并使用get_vect_value_list()
函数获取两个vector
中相同的元素,并将其赋值给item
。最后使用for循环遍历返回两者的交集列表。
#include <iostream> #include <vector> #include <map> #include <string> #include <algorithm> using namespace std ; std ::vector <int > get_vect_value_list (std ::vector <int > VectA, std ::vector <int > VectB) { std ::vector <int > item = {}; std ::vector <int >::iterator iter; if (VectA.size() == VectB.size()) { for (int x = 0 ; x < VectA.size(); x++) { iter = find(VectB.begin(), VectB.end(), VectA[x]); if (iter != VectB.end()) { item.push_back(*iter); } } } return item; } int main (int argc,char * argv[]) { std ::vector <int > VectA = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 }; std ::vector <int > VectB = { 5 , 6 , 7 , 8 , 9 , 4 , 32 , 6 , 8 , 9 }; std ::vector <int > item = get_vect_value_list(VectA, VectB); for (int x = 0 ; x < item.size(); x++) { std ::cout << "A中元素与B中都存在的: " << item[x] << std ::endl ; } std ::system("pause" ); return 0 ; }
11.10 根据键设置字典值 在本程序中,定义了两个函数set_dict_value()
和get_dict_value()
,分别用于设置和获取map
容器中指定key
的value
。在具体实现中,使用STL中的find()
函数来查找指定key的位置,然后通过修改该位置对应的value 的值来实现修改操作;另外,使用该函数还可以避免在添加元素时出现重复的键值对。
在主函数中,先使用insert()
函数向map容器中添加若干键值对;然后使用set_dict_value()
函数将key为1的值修改为1000;接着使用get_dict_value()
函数获取key为3的值;最后使用for循环遍历map容器中的所有键值对,并输出键和值。
读者需要注意,map容器的键和值可以是任意类型,而且键必须是没有重复值的,因为map是依靠键来查找值的。
#include <iostream> #include <vector> #include <map> #include <string> using namespace std ; bool set_dict_value (std ::map <int , int >& ptr, int find_key, int set_value) { std ::map <int , int >::iterator iter; iter = ptr.find(find_key); if (iter != ptr.end()) { iter->second = set_value; return true ; } return false ; } int get_dict_value (std ::map <int , int >& ptr, int find_key) { std ::map <int , int >::iterator iter; iter = ptr.find(find_key); if (iter != ptr.end()) { return iter->second; } return false ; } int main (int argc, char * argv[]) { std ::map <int , int > map ; map .insert(std ::pair <int , int >(1 , 100 )); map .insert(std ::pair <int , int >(2 , 200 )); map .insert(std ::pair <int , int >(3 , 300 )); map .insert(std ::pair <int , int >(4 , 400 )); bool ref = set_dict_value(map , 1 , 1000 ); std ::cout << "设置状态: " << ref << std ::endl ; int _value = get_dict_value(map , 3 ); std ::cout << "获取数据: " << _value << std ::endl ; for (std ::map <int , int >::iterator ptr = map .begin(); ptr != map .end(); ptr++) { std ::cout << "Key: " << ptr->first << " Value: " << ptr->second << std ::endl ; } std ::system("pause" ); return 0 ; }
11.11 实现列表容器计数 这段代码实现了统计一个vector
容器中各个元素出现次数的功能。在具体实现中,使用map
容器来保存元素及其出现次数的对应关系。对于每个元素,先使用count()
函数查找其在map
容器中的出现次数,如果不是第一次出现,则从map
容器中取出其出现次数后递增,再将修改后的次数更新回map
容器;否则,将其次数设置为1。最后,使用for
循环遍历map
容器,并输出元素及其出现次数。
读者需要注意,这段代码中使用了STL中的operator[]
,该运算符在map容器中可以用来访问指定键的值,同时也可以用于添加新的键值对。另外,需要注意count()
函数的返回值类型是size_t
,因此不能和int
类型的变量直接比较大小。
#include <iostream> #include <vector> #include <string> #include <map> using namespace std ; bool set_dict_value (std ::map <int , int >& ptr, int set_key, int set_value) { ptr[set_key] = set_value; return true ; } int get_dict_value (std ::map <int , int >& ptr, int find_key) { std ::map <int , int >::iterator iter; iter = ptr.find(find_key); if (iter != ptr.end()) { return iter->second; } return false ; } int main (int argc, char * argv[]) { std ::map <int , int > map ; std ::vector <int > vect = { 54 , 66 , 78 , 34 , 44 , 44 , 56 , 3 , 4 , 56 , 7 , 89 , 7 , 5 , 34 , 4 , 56 , 7 , 8 , 90 , 0 , 8 , 6 , 4 , 3 }; for (int x = 0 ; x < vect.size(); x++) { int ref = map .count(vect[x]); if (ref != 0 ) { int _value = get_dict_value(map , vect[x]); _value = _value + 1 ; set_dict_value(map , vect[x], _value); } else { set_dict_value(map , vect[x], 1 ); } } for (std ::map <int , int >::iterator iter = map .begin(); iter != map .end(); iter++) { std ::cout << "数字: " << iter->first << " --> 出现次数: " << iter->second << std ::endl ; } std ::system("pause" ); return 0 ; }
11.12 验证两个列表异同点 这段代码演示了如何比较两个vector
容器之间的差异。先定义了两个函数,分别为find_vector_value()
和get_list_value_list()
。
find_vector_value() 函数用于检查某个元素是否存在于vector
容器中。具体实现中,使用STL中的find()
函数来查找指定元素的位置,如果该元素存在于容器中,则返回 true;否则返回 false。
get_list_value_list() 函数用于比较两个vector
容器之间的差异。具体实现中,先判断两个容器的长度是否相等,如果不相等则直接返回false。否则,对于vectorA
容器中的每个元素,都调用find_vector_value()
函数查找其是否存在于vectorB
容器中;如果存在,则将该元素添加到result_identical
容器中,否则,将其添加到result_different
容器中。最后,该函数返回true,表示执行成功。
在主函数中,先定义了两个vector
容器x
和y
,然后调用get_list_value_list()
函数,将x
和y
之间的差异分别存储在名为identical
和different
的容器中。最后,使用for
循环遍历这两个容器,并输出它们所包含的元素。
#include <iostream> #include <vector> #include <string> #include <algorithm> using namespace std ; bool find_vector_value (std ::vector <int > ptr, int find_value) { std ::vector <int >::iterator iter; if (ptr.size() >= 0 ) { for (int x = 0 ; x < ptr.size(); x++) { iter = find(ptr.begin(), ptr.end(), find_value); if (iter != ptr.end()) { return true ; } } } return false ; } bool get_list_value_list (std ::vector <int > vect_a, std ::vector <int > vect_b, std ::vector <int >& result_identical, std ::vector <int >& result_different) { std ::vector <int >::iterator iter; if (vect_a.size() == vect_b.size()) { for (int x = 0 ; x < vect_a.size(); x++) { bool ref = find_vector_value(vect_b, vect_a[x]); if (ref == true ) { result_identical.push_back(vect_a[x]); } else if (ref != true ) { result_different.push_back(vect_a[x]); } } return true ; } return false ; } int main (int argc,char * argv[]) { std ::vector <int > x = { 23 , 56 , 55 , 43 , 7 , 8 , 9 , 0 , 5 , 4 , 6 , 7 , 8 , 9 , 4 }; std ::vector <int > y = { 23 , 56 , 55 , 334 , 7 , 8 , 9 , 0 , 5 , 4 , 6 , 7 , 8 , 9 , 4 }; std ::vector <int > identical; std ::vector <int > different; get_list_value_list(x, y, identical, different); for (int x = 0 ; x < identical.size(); x++) { std ::cout << "x中存在的元素: " << identical[x] << std ::endl ; } for (int x = 0 ; x < different.size(); x++) { std ::cout << "x中不存在的元素: " << different[x] << std ::endl ; } std ::system("pause" ); return 0 ; }
11.13 实现两个列表合并 这段代码实现了将两个vector
容器中的元素进行合并的功能。具体实现中,使用extend_vector_list()
函数来实现。
extend_vector_list() 函数用于合并两个vector
容器中的元素。该函数有三个参数,分别为vect_x、vect_y
和ignore
。其中,vect_x
和vect_y
分别表示要进行合并的两个vector
容器;ignore 参数表示是否忽略重复元素,如果为 true,则在合并过程中会自动去重,否则会保留重复元素。
具体实现中,先将vect_x
中的所有元素添加到item
容器中,然后将vect_y
中的所有元素依次逐个进行查找,根据ignore
参数的不同处理方式,对于不存在于item
容器中的元素,将其添加到item
容器中。最后,该函数返回item
容器,表示执行成功。
在主函数中,先定义了两个要合并的vector
容器x
和y
,然后调用extend_vector_list()
函数进行合并。因为ignore
参数设置为 true,所以在合并过程中会自动去除重复元素。最后使用for循环遍历合并后的vect
容器,并输出它们所包含的元素。
#include <iostream> #include <vector> #include <map> #include <string> #include <algorithm> using namespace std ; bool find_vector_value (std ::vector <int > ptr, int find_value) { std ::vector <int >::iterator iter; if (ptr.size() >= 0 ) { for (int x = 0 ; x < ptr.size(); x++) { iter = find(ptr.begin(), ptr.end(), find_value); if (iter != ptr.end()) { return true ; } } } return false ; } std ::vector <int > extend_vector_list (std ::vector <int > &vect_x, std ::vector <int > &vect_y, bool ignore = false ) { std ::vector <int > item; for (int x = 0 ; x < vect_x.size(); x++) { item.push_back(vect_x[x]); } for (int x = 0 ; x < vect_y.size(); x++) { if (ignore == true ) { bool ref = find_vector_value(item, vect_y[x]); if (ref != true ) { item.push_back(vect_y[x]); } } else { item.push_back(vect_y[x]); } } return item; } int main (int argc,char * argv[]) { std ::vector <int > vect; std ::vector <int > x = { 1 , 2 , 3 , 4 , 5 }; std ::vector <int > y = { 5 , 6 , 7 , 8 , 9 , 10 , 11 }; vect = extend_vector_list(x, y, true ); for (int x = 0 ; x < vect.size(); x++) { std ::cout << "合并后: " << vect[x] << std ::endl ; } std ::system("pause" ); return 0 ; }
11.14 字典与列表的嵌套 对于嵌套列表的实现,代码首先定义了一个vector
容器vect
,该容器中的每个元素都是另一个vector
容器。通过push_back()
函数,将两个内部vector
容器的元素添加到外部的vect
容器中。然后使用两层for
循环遍历外部和内部的容器,并输出它们所包含的每一个子元素。
对于嵌套多个字典的实现,代码定义了一个vector
容器vect
,该容器中的每个元素都是一个map
容器。map容器中的一个key
对应一个vector
容器。通过push_back()
函数,将两个内部map容器的元素添加到外部的vect容器中。然后使用两层for
循环遍历外部和内部的容器,并输出它们所包含的每一个子元素。
对于解析内部map
容器中的元素,需要使用迭代器进行遍历,具体实现还将其中的vector
容器解析出来,并输出其中的每一个元素。
#include <iostream> #include <vector> #include <map> #include <string> using namespace std ; void list_nesting_list () { std ::vector <std ::vector <std ::string >> vect; std ::vector <std ::string > tmp; tmp.push_back("192.168.1.1" ); tmp.push_back("root" ); tmp.push_back("1233" ); vect.push_back(tmp); tmp.clear(); tmp.push_back("192.168.1.2" ); tmp.push_back("lyshark" ); tmp.push_back("123456" ); vect.push_back(tmp); for (int x = 0 ; x < vect.size(); x++) { for (int y = 0 ; y < vect[x].size(); y++) { std ::cout << vect[x][y] << std ::endl ; } } } void list_nesting_dict () { std ::vector < std ::map <std ::string , std ::vector <int > > > vect; std ::vector <int > internal; std ::string internal_string; std ::map <std ::string , std ::vector <int > > map ; internal_string = "192.168.1.1" ; internal = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 }; map [internal_string] = internal; vect.push_back(map ); internal.clear(); internal_string.clear(); map .clear(); internal_string = "192.168.1.2" ; internal = { 1 , 2 , 3 , 4 , 5 , 6 }; map [internal_string] = internal; vect.push_back(map ); for (int x = 0 ; x < vect.size(); x++) { std ::map <std ::string , std ::vector <int >>::iterator iter; for (iter = vect[x].begin(); iter != vect[x].end(); iter++) { std ::cout << "Key: " << iter->first << std ::endl ; std ::vector <int > vector_ptr = iter->second; for (int y = 0 ; y < vector_ptr.size(); y++) { std ::cout << vector_ptr[y] << std ::endl ; } } } } int main (int argc,char * argv[]) { list_nesting_dict(); list_nesting_list(); std ::system("pause" ); return 0 ; }
11.15 可存储多类型容器 这段代码使用了boost
库的variant
类型,实现了一个可变类型容器,用来存储两种不同类型,代码首先定义了一个名为var
的variant
类型数组,其大小为 3,可以容纳两种不同类型的vector
容器。同时,它将一个std::vectorstd::string
和std::vector<int>
赋值给var
数组的第0
个和第1
个元素。
随后,代码使用循环遍历该数组,通过boost
库的get
函数获取存储在var
数组中的元素。如果顺利获取到该元素,则可以进行类型判断,从中提取出对应的vector
容器。
最后,代码使用循环遍历表示vector
容器内部的元素,并输出每一个元素的值。
#include <iostream> #include <string> #include <vector> #include <boost/variant.hpp> using namespace std ; using namespace boost; int main (int argc, char const *argv[]) { boost::variant < std ::vector <std ::string >, std ::vector <int >> var[3 ]; std ::vector <std ::string > string_ptr; string_ptr.push_back("string1" ); string_ptr.push_back("strin2" ); string_ptr.push_back("strin3" ); var[0 ] = string_ptr; std ::vector <int > int_ptr; int_ptr.push_back(1 ); int_ptr.push_back(2 ); int_ptr.push_back(3 ); var[1 ] = int_ptr; for (int x = 0 ; x < 2 ; x++) { if (var[x].type() == typeid(std ::vector <std ::string >)) { std ::vector <std ::string > string_vect; string_vect = boost::get< std ::vector <std ::string > >(var[0 ]); for (int x = 0 ; x < string_vect.size(); x++) { std ::cout << "字符串结构: " << string_vect[x] << std ::endl ; } } else if (var[x].type() == typeid(std ::vector <int >)) { std ::vector <int > int_vect; int_vect = boost::get< std ::vector <int > >(var[1 ]); for (int x = 0 ; x < int_vect.size(); x++) { std ::cout << "整数结构: " << int_vect[x] << std ::endl ; } } } std ::system("pause" ); return 0 ; }
11.16 列表随机弹出元素 这段代码通过使用标准库和boost
库提供的随机数生成器方法,实现了从一个字符串vector
容器中随机弹出一个元素的功能。
函数get_random_value
使用标准库的srand()
函数配合std::rand()
函数实现随机生成整数。该随机生成器并不是真正的随机数生成器,而是伪随机数生成器。函数接受一个vector
容器,并返回其中随机抽取的一个元素。
函数get_boost_random_value
使用boost
库提供的mt19937
和uniform_int<>
类型的随机生成器实现真随机数的生成。该函数的实现相对更加健壮,并且需要的代码量也更多。此函数也接受一个vector
容器,并返回其中随机抽取的一个元素。
在main()
函数中,将标准库和boost
版本的随机函数各循环执行了10
次,并在每轮循环中输出从vector
容器中随机取出的元素。需要注意的是,在标准库实现弹出随机数的函数中,随机数生成器需要使用当前的系统时间作为种子,因此可产生结果不同的随机数序列。而在boost
实现的随机弹出元素的函数中,每次的随机数序列是非常随机且预测不可能的。
关于选择哪种生成随机数的方法,需根据实际情况进行选择。若仅是生成一些简单的随机数,则标准库的伪随机数生成器就足够使用;若需要生成复杂和预测性极低的应用程序,则需使用boost
库的真随机数生成器。
#include <iostream> #include <stdlib.h> #include <string> #include <vector> #include <time.h> #include <boost/random.hpp> #include <boost/random/random_device.hpp> using namespace std ; using namespace boost; std ::string get_random_value (std ::vector <std ::string > &ptr) { srand(unsigned (time(0 ))); int count = ptr.size(); std ::string ref = ptr.at(std ::rand() % count); return ref; } std ::string get_boost_random_value (std ::vector <std ::string > &ptr) { boost::mt19937 gen; boost::uniform_int<>distribut(1 , 10 ); boost::variate_generator<mt19937 &, uniform_int<>> die(gen, distribut); int count = ptr.size(); std ::string ref = ptr.at(std ::rand() % count); return ref; } int main (int argc, char * argv[]) { std ::vector <std ::string > vect; vect.push_back("admin" ); vect.push_back("lyshark" ); vect.push_back("location" ); vect.push_back("root" ); for (int x = 0 ; x < 10 ; x++) { std ::string ref = get_random_value(vect); std ::cout << "标准库随机元素: " << ref << std ::endl ; } for (int x = 0 ; x < 10 ; x++) { std ::string ref = get_boost_random_value(vect); std ::cout << "boost 随机元素: " << ref << std ::endl ; } std ::system("pause" ); return 0 ; }
11.17 实现队列参数计算 这段代码定义了一个MyData
类,包括两个数据成员uuid
和uname
,以及一个get()
函数。该函数将传入的两个整数参数与uuid
进行加法计算,并返回计算结果。
在main()
函数中,定义了一个std::queue<MyData>
类型的队列对象queue_ptr
,插入了5
个MyData
类型的元素。接下来,在一个while
循环中,将队列顶部的元素取出,并根据MyData
对象的get()
函数计算它的数值加和。将计算结果与名字信息组成std::pair<std::string, int>
按顺序添加到一个vector
容器check_sum_list
中。
最后,循环遍历check_sum_list
向控制台输出每个std::pair<std::string, int>
元素的内容。
#include <iostream> #include <string> #include <vector> #include <queue> using namespace std ; class MyData { public: int uuid; std ::string uname; MyData(int x, std ::string y) { uuid = x; uname = y; } int get (int value_a, int value_b) { return uuid + value_a + value_b; } }; int main (int argc, char *argv[]) { std ::vector <std ::pair <std ::string , int >> check_sum_list; std ::queue <MyData> queue_ptr; queue_ptr.push(MyData(1001 , "admin" )); queue_ptr.push(MyData(1002 , "lyshark" )); queue_ptr.push(MyData(1003 , "root" )); queue_ptr.push(MyData(1004 , "zhangsan" )); queue_ptr.push(MyData(1005 , "wangwu" )); while (!queue_ptr.empty()) { std ::pair <std ::string , int > temp; MyData ptr = queue_ptr.front(); int ref = ptr.get(100 , 200 ); temp.first = ptr.uname; temp.second = ref; check_sum_list.push_back(temp); queue_ptr.pop(); } for (int x = 0 ; x <= check_sum_list.size(); x++) { std ::cout << check_sum_list[x].first << check_sum_list[x].second << std ::endl ; } std ::system("pause" ); return 0 ; }
11.18 查找最大值/最小值 这段代码演示了如何使用Boost
库的minmax_element
算法,在一个vector
容器中找到最大值和最小值,并找到最小值对应的条目。
find_list() 函数演示了如何在一个整数容器中找到最大值和最小值,以及如何查找第一个最小值和最后一个最小值的下标。
find_dict_minmax_element() 函数演示了如何在一个std::pair<int, std::string>
容器中找到最小值和最大值,并返回最小值对应的std::pair<int, std::string>
条目。
需要时,可以在比较函数中指定自定义的元素排序方式。如果在重载的比较函数中返回的是 bool 值,那么此函数找到的是容器中的单个元素,而不是元素的下标。如果返回的是迭代器,那么这个函数找到的则是对应下标位置的元素。
#include <iostream> #include <string> #include <vector> #include <boost/algorithm/minmax_element.hpp> using namespace std ; void find_list () { std ::vector <int > vec = { 1 , 4 , 3 , 2 , 5 , 6 , 6 , 6 , 7 , 8 , 1 , 4 }; auto x = boost::minmax_element(vec.begin(), vec.end()); cout << "最小值: " << *x.first << endl ; cout << "最大值: " << *x.second << endl ; decltype(vec.begin()) pos; pos = boost::first_min_element(vec.begin(), vec.end()); cout << "第一个最小值: " << *pos << " 数组中位置: " << pos - vec.begin() << endl ; pos = boost::last_min_element(vec.begin(), vec.end()); cout << "最后一个最小值: " << *pos << " 数组中位置: " << pos - vec.begin() << endl ; } std ::pair <int ,std ::string > find_dict_minmax_element (std ::vector <std ::pair <int ,std ::string >> ptr) { std ::vector <int > vect_ptr; for (int x = 0 ; x < ptr.size(); x++) { vect_ptr.push_back(x); } auto x = boost::minmax_element(vect_ptr.begin(), vect_ptr.end()); std ::pair <int , std ::string > ref = ptr.at(*x.first); return ref; } int main (int argc, char *argv[]) { std ::vector <std ::pair <int , std ::string >> ptr; ptr.push_back(std ::pair < int , std ::string >(98 , "zhsngsan" )); ptr.push_back(std ::pair < int , std ::string >(65 , "lisi" )); ptr.push_back(std ::pair < int , std ::string >(49 , "wangwu" )); std ::pair <int , std ::string > get = find_dict_minmax_element(ptr); std ::cout << "姓名: " << get.second << std ::endl ; std ::cout << "分数: " << get.first << std ::endl ; std ::system("pause" ); return 0 ; }
11.19 字典中嵌套结构体 这段代码演示了如何将自定义结构存储在map
容器中,并对这些结构进行迭代遍历和访问。MyStruct定义了一个自定义的结构类型,包括两个整数成员变量x
和y
,以及CheckSum()
函数,该函数计算x
和y
的和并返回结果。
在main
函数中,三个MyStruct
类型的结构对象struct_ptr_a、struct_ptr_b
和struct_ptr_c
分别设置了不同的x
和y
值,然后将它们插入到map
容器中,每个结构对象的唯一键值std::pair<int, MyStruct>(1, struct_ptr_a)
、std::pair<int, MyStruct>(2, struct_ptr_b)
和std::pair<int, MyStruct>(3, struct_ptr_c)
用于在map
容器中存储对应结构。
接下来使用for
循环迭代遍历结构体,并使用迭代器it
访问map
容器中的值。使用it->first
访问结构的键值,使用it->second.x
和it->second.y
访问结构的x
和y
成员变量,使用it->second.CheckSum()
访问结构的CheckSum()
函数的返回值。在控制台输出取出结构元素的值和计算结果。
#include <iostream> #include <string> #include <map> using namespace std ; typedef struct { int x; int y; int CheckSum () { return x + y; } }MyStruct; typedef std ::map <int , MyStruct> struct_map;int main (int argc, char * argv[]) { struct_map map ; MyStruct struct_ptr_a, struct_ptr_b, struct_ptr_c; struct_ptr_a.x = 100 ; struct_ptr_a.y = 200 ; struct_ptr_b.x = 10 ; struct_ptr_b.y = 20 ; struct_ptr_c.x = 12 ; struct_ptr_c.y = 30 ; map .insert(std ::pair <int , MyStruct>(1 , struct_ptr_a)); map .insert(std ::pair <int , MyStruct>(2 , struct_ptr_b)); map .insert(std ::pair <int , MyStruct>(3 , struct_ptr_c)); for (struct_map::iterator it = map .begin(); it != map .end(); it++) { std ::cout << "Key: " << it->first << " Value X: " << it->second.x << std ::endl ; std ::cout << "函数返回值: " << it->second.CheckSum() << std ::endl ; } std ::system("pause" ); return 0 ; }