C++ Boost 2 容器
在线文档:http://www.boost.org/doc/
离线文档:解压Boost压缩包,浏览boost_1_62_0/boost_1_62_0/libs/libraries.htm#Containers
目录: Boost any 容器 引用与指针复习,引用并不会退化 boost.tuple,类似STL的pair键值对,但是tuple可以装10种不同的任意数据类型 tuple的创建,值操作要注意的 tuple.tie:创建一个所有元素类型为非const引用的tuple tuple IO设定输出格式,只接受固定格式的输入 Boost.array Boost.unordered 无序数据插入 Boost,unordered hash_map桶的分布情况 Boost:Multi-Array 多维数组 Boost 多维数组, Boost.Property Map Key,value Property Tree 解析XML文件 Property Tree 生成XML文件 Property Tree 解析JSON文件 Property Tree 生成JSON文件
Boost any 容器
chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include <list> #include <boost/any.hpp> using boost::any_cast; typedef std::list<boost::any> many; void append_int(many & values, int value) { boost::any to_append = value; values.push_back(to_append); } void append_string(many & values, const std::string & value) { values.push_back(value); } void append_char_ptr(many & values, const char * value) { values.push_back(value); } void append_any(many & values, const boost::any & value) { values.push_back(value); } void append_nothing(many & values) { values.push_back(boost::any()); } bool is_empty(const boost::any & operand) { return operand.empty(); } bool is_int(const boost::any & operand) { return operand.type() == typeid(int); } bool is_char_ptr(const boost::any & operand) { try { any_cast<const char *>(operand); return true; } catch(const boost::bad_any_cast &) { return false; } } bool is_string(const boost::any & operand) { return any_cast<std::string>(&operand); } void count_all(many & values, std::ostream & out) { out << "#empty == " << std::count_if(values.begin(), values.end(), is_empty) << std::endl; out << "#int == " << std::count_if(values.begin(), values.end(), is_int) << std::endl; out << "#const char * == " << std::count_if(values.begin(), values.end(), is_char_ptr) << std::endl; out << "#string == " << std::count_if(values.begin(), values.end(), is_string) << std::endl; } int main() { many m1; append_int(m1,128); append_int(m1,65535); append_char_ptr(m1,"Hello"); append_string(m1,"Hello"); append_nothing(m1); count_all(m1,std::cout); } chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out #empty == 1 #int == 2 #const char * == 1 #string == 1 chunli@Linux:~/boost$
引用与指针复习,引用并不会退化
chunli@Linux:~/boost$ cat main.cpp #include <iostream> void fun1(int (&a)[20]) { std::cout << sizeof(a) << std::endl; std::cout << a[0] << std::endl; std::cout << a[1] << std::endl; } void fun2(int *a) { std::cout << a[0] << std::endl; std::cout << a[1] << std::endl; } int main() { int a[20]; a[0] = 1; a[1] = 111; fun1(a); fun2(a); return 0; } chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out 80 1 111 1 111 chunli@Linux:~/boost$
boost.tuple,类似STL的pair键值对,但是tuple可以装10种不同的任意数据类型
tuple的创建,值操作要注意的
chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include <boost/tuple/tuple.hpp> class A{}; int main() { using boost::tuple; double d = 2.7; A a; tuple<int,double&,const A&> t(1,d,a); //创建tuple对象 ++boost::get<0>(t); int i = boost::get<0>(t); i = t.get<0>(); boost::get<0>(t) = 5; A aa = boost::get<2>(t); //接收对象 //A aa = boost::get<3>(t); //下标溢出 double e = boost::get<1>(t); //数据类型自动转换 boost::get<1>(t) = 3.14; //修改值 //boost::get<2>(t) = "hello"; //数据类型不匹配 const tuple<int,double&,const A&> ct = t;//创建tuple对象 int j = boost::get<0>(ct); //boost::get<0>(ct) = 5;//无法修改 const数据类型 return 0; } chunli@Linux:~/boost$ g++ main.cpp && ./a.out chunli@Linux:~/boost$
tuple.tie:创建一个所有元素类型为非const引用的tuple
chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include <boost/tuple/tuple.hpp> int main() { int i; char c; double d; boost::tie(i,c,d); //通过boost::tuple 来修改 boost::tie(i,c,d) = boost::tuple<int,char,double>(1,'A',3.1415926); std::cout<<i<<std::endl; std::cout<<c<<std::endl; std::cout<<d<<std::endl; char e; boost::tie(boost::tuples::ignore,e) = std::make_pair(1,'a');//ignore std::cout<<e<<std::endl; return 0; } chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out 1 A 3.14159 a chunli@Linux:~/boost$
tuple IO设定输出格式,只接受固定格式的输入
chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include <boost/tuple/tuple_io.hpp> using namespace std; int main() { //输出 //默认输出 (1 602214129 Hello Boost!) boost::tuple<float,int,string> a(1.0f,602214129,string("Hello Boost!")); cout << a << endl; //自定义输出格式 [1,602214129,Hello Boost!] boost::tuple<float,int,string> b(1.0f,602214129,string("Hello Boost!")); cout << boost::tuples::set_open('[') << boost::tuples::set_close(']') << boost::tuples::set_delimiter(',') << b << endl; //输入 boost::tuple<int,int,int> i; cin >>i ; cout << i <<endl; boost::tuple<int,int> j; cin >> boost::tuples::set_open('[') >> boost::tuples::set_close(']') >> boost::tuples::set_delimiter(':'); cin >> j; cout << j << endl; return 0; } chunli@Linux:~/boost$ chunli@Linux:~/boost$ g++ main.cpp && ./a.out (1 602214129 Hello Boost!) [1,602214129,Hello Boost!] (123 321 213) [123,321,213] [123:321] [123,321] chunli@Linux:~/boost$ g++ main.cpp && ./a.out (1 602214129 Hello Boost!) [1,602214129,Hello Boost!] 234 567 890 [0,0,0] [0,0] chunli@Linux:~/boost$
Boost.array
chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include <algorithm> #include <boost/array.hpp> using namespace std; int main() { //boost::array<int,10> arr1 = {9,1,8,2,7,3,6,4,0,5};//创建一个装int类型,容量是10个 boost::array<int,10> arr1 = {{9,1,8,2,7,3,6,4,0,5}};//创建一个装int类型,容量是10个 sort(arr1.begin(),arr1.end()); copy(arr1.begin(),arr1.end(),ostream_iterator<int>(cout," ")); return 0; } chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out 0 1 2 3 4 5 6 7 8 9 chunli@Linux:~/boost$
Boost.unordered 数据插入
chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include <boost/unordered_map.hpp> using namespace std; template<typename Iter> void print(Iter first,Iter last) { while(first != last) { cout << first->first << "," << first->second << endl; first++; } } int main() { boost::unordered_map<string,int> map1; map1.insert(make_pair("Hello Boost",11)); map1.insert(make_pair("Hello World",12)); map1.insert(make_pair("Hello Linux",13)); map1.insert(make_pair("Hello C++",14)); map1["apple"] = 666; map1["banana"] = 777; map1["pare"] = 888; //map1["X2"],对map下标操作,如果key不存在,就插入.尽量少用这种费解的语法 cout << map1["对map下标操作,如果key不存在,就插入"] << endl;//打印 0 print(map1.begin(),map1.end()); return 0; } chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out 0 pare,888 banana,777 对map下标操作,如果key不存在,就插入,0 apple,666 Hello C++,14 Hello Linux,13 Hello World,12 Hello Boost,11 chunli@Linux:~/boost$
Boost,unordered hash_map桶的分布情况
chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include <boost/unordered_map.hpp> using namespace std; template<typename Iter> void print(Iter first,Iter last) { while(first != last) { cout << first->first << "," << first->second << endl; first++; } } int main() { boost::unordered_map<string,int> map1; map1.insert(make_pair("Hello Boost",11)); map1.insert(make_pair("Hello World",12)); map1.insert(make_pair("Hello Linux",13)); map1.insert(make_pair("Hello C++",14)); map1["apple"] = 666; map1["banana"] = 777; map1["pare"] = 888; //map1["X2"],对map下标操作,如果key不存在,就插入.尽量少用这种费解的语法 cout << map1["对map下标操作,如果key不存在,就插入"] << endl;//打印 0 print(map1.begin(),map1.end()); /////////////////// 查看有多少个元素///////////////////////////// cout << "map1 size:"<<map1.size() << endl;//map1 size:3 /////////////////// 查看有多少个桶///////////////////////////// cout << "当前共有" << map1.bucket_count() << "个桶" << endl; /////////////////// 查看每个桶的分布情况///////////////////////////// cout << "每个桶的情况如下" << endl; int n = map1.bucket_count(); for(int i = 0;i<n;i++) { cout << "Bucket #" <<i <<":" << map1.bucket_size(i) << endl; } cout << "-------------------------------------------"<< endl; typedef boost::unordered_map<string,int>::local_iterator LIter; for(LIter it = map1.begin(0);it != map1.end(0);++it) { cout << it->first << " " <<it->second << endl; } return 0; } chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out 0 pare,888 banana,777 对map下标操作,如果key不存在,就插入,0 apple,666 Hello C++,14 Hello Linux,13 Hello World,12 Hello Boost,11 map1 size:8 当前共有16个桶 每个桶的情况如下 Bucket #0:2 Bucket #1:0 Bucket #2:0 Bucket #3:0 Bucket #4:0 Bucket #5:0 Bucket #6:1 Bucket #7:1 Bucket #8:1 Bucket #9:2 Bucket #10:0 Bucket #11:1 Bucket #12:0 Bucket #13:0 Bucket #14:0 Bucket #15:0 ------------------------------------------- Hello Linux 13 Hello World 12 chunli@Linux:~/boost$
Boost:Multi-Array 多维数组
chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include "boost/multi_array.hpp" #include "boost/cstdlib.hpp" using namespace std; int main () { // Create a 3D array that is 3 x 4 x 2 typedef boost::multi_array<double, 3> array; array A(boost::extents[3][4][2]); // Assign a value to an element in the array A[0][0][0] = 3.14; if(A[0][0][0] == 3.14) { cout << "yes!" << endl; } else { cout << "no!" << endl; } return 0; } chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out yes! chunli@Linux:~/boost$
Boost 多维数组,
chunli@Linux:~/boost$ cat main.cpp #include <stdio.h> #include "boost/multi_array.hpp" #include "boost/array.hpp" #include "boost/cstdlib.hpp" using namespace std; int main () { boost::array<int, 3> shape = {{ 5, 5, 5 }};//普通数组 ,装3个数据 boost::multi_array<int, 3> A(shape); //设定3个维度的大小 /////////////填充//////////////////////// for(int i=0;i<5;i++) { for(int j=0;j<5;j++) { for(int k=0;k<5;k++) { A[i][j][k] = (i+j+k)*(i+j+k); } } } ////////////遍历///////////////////////////// for(int i=0;i<5;i++) { for(int j=0;j<5;j++) { for(int k=0;k<5;k++) { printf("A[%d][%d][%d]=%3d,",i,j,k,A[i][j][k]); } printf("\n"); } printf("\n"); } return 0; } chunli@Linux:~/boost$ g++ main.cpp && ./a.out A[0][0][0]= 0,A[0][0][1]= 1,A[0][0][2]= 4,A[0][0][3]= 9,A[0][0][4]= 16, A[0][1][0]= 1,A[0][1][1]= 4,A[0][1][2]= 9,A[0][1][3]= 16,A[0][1][4]= 25, A[0][2][0]= 4,A[0][2][1]= 9,A[0][2][2]= 16,A[0][2][3]= 25,A[0][2][4]= 36, A[0][3][0]= 9,A[0][3][1]= 16,A[0][3][2]= 25,A[0][3][3]= 36,A[0][3][4]= 49, A[0][4][0]= 16,A[0][4][1]= 25,A[0][4][2]= 36,A[0][4][3]= 49,A[0][4][4]= 64, A[1][0][0]= 1,A[1][0][1]= 4,A[1][0][2]= 9,A[1][0][3]= 16,A[1][0][4]= 25, A[1][1][0]= 4,A[1][1][1]= 9,A[1][1][2]= 16,A[1][1][3]= 25,A[1][1][4]= 36, A[1][2][0]= 9,A[1][2][1]= 16,A[1][2][2]= 25,A[1][2][3]= 36,A[1][2][4]= 49, A[1][3][0]= 16,A[1][3][1]= 25,A[1][3][2]= 36,A[1][3][3]= 49,A[1][3][4]= 64, A[1][4][0]= 25,A[1][4][1]= 36,A[1][4][2]= 49,A[1][4][3]= 64,A[1][4][4]= 81, A[2][0][0]= 4,A[2][0][1]= 9,A[2][0][2]= 16,A[2][0][3]= 25,A[2][0][4]= 36, A[2][1][0]= 9,A[2][1][1]= 16,A[2][1][2]= 25,A[2][1][3]= 36,A[2][1][4]= 49, A[2][2][0]= 16,A[2][2][1]= 25,A[2][2][2]= 36,A[2][2][3]= 49,A[2][2][4]= 64, A[2][3][0]= 25,A[2][3][1]= 36,A[2][3][2]= 49,A[2][3][3]= 64,A[2][3][4]= 81, A[2][4][0]= 36,A[2][4][1]= 49,A[2][4][2]= 64,A[2][4][3]= 81,A[2][4][4]=100, A[3][0][0]= 9,A[3][0][1]= 16,A[3][0][2]= 25,A[3][0][3]= 36,A[3][0][4]= 49, A[3][1][0]= 16,A[3][1][1]= 25,A[3][1][2]= 36,A[3][1][3]= 49,A[3][1][4]= 64, A[3][2][0]= 25,A[3][2][1]= 36,A[3][2][2]= 49,A[3][2][3]= 64,A[3][2][4]= 81, A[3][3][0]= 36,A[3][3][1]= 49,A[3][3][2]= 64,A[3][3][3]= 81,A[3][3][4]=100, A[3][4][0]= 49,A[3][4][1]= 64,A[3][4][2]= 81,A[3][4][3]=100,A[3][4][4]=121, A[4][0][0]= 16,A[4][0][1]= 25,A[4][0][2]= 36,A[4][0][3]= 49,A[4][0][4]= 64, A[4][1][0]= 25,A[4][1][1]= 36,A[4][1][2]= 49,A[4][1][3]= 64,A[4][1][4]= 81, A[4][2][0]= 36,A[4][2][1]= 49,A[4][2][2]= 64,A[4][2][3]= 81,A[4][2][4]=100, A[4][3][0]= 49,A[4][3][1]= 64,A[4][3][2]= 81,A[4][3][3]=100,A[4][3][4]=121, A[4][4][0]= 64,A[4][4][1]= 81,A[4][4][2]=100,A[4][4][3]=121,A[4][4][4]=144, chunli@Linux:~/boost$
Boost.Property Map
chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include <map> #include <string> #include <boost/property_map/property_map.hpp> template <typename AddressMap> void foo(AddressMap address) { std::cout << "foo: "<< sizeof(address) << std::endl; typedef typename boost::property_traits<AddressMap>::key_type key_type; typedef typename boost::property_traits<AddressMap>::value_type value_type; value_type old_address, new_address; key_type fred = "Fred"; old_address = get(address, fred); new_address = "384 Fitzpatrick Street"; put(address, fred, new_address); key_type joe = "工程师"; value_type& joes_address = address[joe]; joes_address = "西湖 中国浙江"; } int main() { std::map<std::string, std::string> name2address; boost::associative_property_map < std::map<std::string, std::string> > address_map(name2address); std::cout << "std::map<std::string, std::string> :" << sizeof(name2address) << std::endl; name2address.insert(make_pair(std::string("Fred"),std::string("710 West 13th Street"))); name2address.insert(make_pair(std::string("Joe"), std::string("710 West 13th Street"))); std::cout << "std::map<std::string, std::string> :" << sizeof(name2address) << std::endl; foo(address_map); for (std::map<std::string, std::string>::iterator i = name2address.begin();i != name2address.end(); i++) { std::cout << i->first << ": " << i->second << std::endl; } return EXIT_SUCCESS; } chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out std::map<std::string, std::string> :48 std::map<std::string, std::string> :48 foo: 8 Fred: 384 Fitzpatrick Street Joe: 710 West 13th Street 工程师: 西湖 中国浙江 chunli@Linux:~/boost$
Property Tree 解析XML文件
chunli@Linux:~/boost$ cat debug_persons.xml <debug> <total>3</total> <persons> <person> <age>23</age> <name>hugo</name> </person> <person> <age>23</age> <name>mayer</name> </person> <person> <age>30</age> <name>boy</name> </person> </persons> </debug> chunli@Linux:~/boost$ chunli@Linux:~/boost$ cat main.cpp #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/xml_parser.hpp> #include <boost/foreach.hpp> #include <vector> #include <string> #include <exception> #include <iostream> struct person { int age; std::string name; }; struct debug_persons { int itsTotalNumber; std::vector<person> itsPersons; void load(const std::string& filename); void save(const std::string& filename); }; std::ostream& operator<<(std::ostream& o,const debug_persons& dp) { o << "totoal:" << dp.itsTotalNumber << "\n"; o << "persons\n"; BOOST_FOREACH(const person& p,dp.itsPersons) { o << "\tperson: Age:" << p.age << " Nmae:" << p.name << "\n"; } return o; } void debug_persons::save( const std::string& filename ) { using boost::property_tree::ptree; ptree pt; pt.put("debug.total", itsTotalNumber); BOOST_FOREACH(const person& p,itsPersons) { ptree child; child.put("age",p.age); child.put("name",p.name); pt.add_child("debug.persons.person",child); } // Write property tree to XML file write_xml(filename, pt); } void debug_persons::load( const std::string& filename ) { using boost::property_tree::ptree; ptree pt; read_xml(filename, pt); itsTotalNumber = pt.get<int>("debug.total"); BOOST_FOREACH(ptree::value_type &v, pt.get_child("debug.persons")) { //m_modules.insert(v.second.data()); person p; p.age = v.second.get<int>("age"); p.name = v.second.get<std::string>("name"); itsPersons.push_back(p); } } int main(int argc, char* argv[]) { try { debug_persons dp; dp.load("debug_persons.xml"); std::cout<<dp<<std::endl; person p; p.age = 100; p.name = "old man"; dp.itsPersons.push_back(p); dp.save("new.xml"); std::cout << "Success\n"; } catch (std::exception &e) { std::cout << "Error: " << e.what() << "\n"; } return 0; } chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out totoal:3 persons person: Age:23 Nmae:hugo person: Age:23 Nmae:mayer person: Age:30 Nmae:boy Success chunli@Linux:~/boost$
Property Tree 生成XML文件
chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/xml_parser.hpp> #include <boost/foreach.hpp> #include <string> #include <vector> using namespace std; int main(int argc, char** argv) { vector<string> vect_str; vector<string>::iterator it; vect_str.push_back("111111"); vect_str.push_back("222222"); vect_str.push_back("333333"); vect_str.push_back("444444"); using namespace boost::property_tree; ptree pt; //定义一个树pt ptree out; ptree cond; ptree rule; ptree data ; ptree info ; for (it = vect_str.begin(); it != vect_str.end(); it++) //迭代vector { data.put("<xmlattr>.key",it->data()); info.add_child("data",data); data.clear() ; } pt.add_child("root.output.info",info); info.clear(); BOOST_FOREACH(std::string& str, vect_str) //迭代vector { for (int i = 0; i < 2; i++) { cond.put("<xmlattr>.desc", "123"); cond.put("<xmlattr>.path", "345"); cond.put("<xmlattr>.version", "567"); cond.put("<xmlattr>.priority", "789"); rule.add_child("cond", cond); cond.clear(); } out.put("<xmlattr>.where", str); rule.add_child("out",out); out.clear(); pt.add_child("root.output.rule", rule); rule.clear(); } //设置写入xml文件的格式, boost::property_tree::xml_writer_settings<string> settings = boost::property_tree::xml_writer_make_settings<string> (' ', 4); //把property_tree 转为XML文件 write_xml("newconfig.xml", pt, std::locale(), settings); return 0; } chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out chunli@Linux:~/boost$ cat newconfig.xml <?xml version="1.0" encoding="utf-8"?> <root> <output> <info> <data key="111111"/> <data key="222222"/> <data key="333333"/> <data key="444444"/> </info> <rule> <cond desc="123" path="345" version="567" priority="789"/> <cond desc="123" path="345" version="567" priority="789"/> <out where="111111"/> </rule> <rule> <cond desc="123" path="345" version="567" priority="789"/> <cond desc="123" path="345" version="567" priority="789"/> <out where="222222"/> </rule> <rule> <cond desc="123" path="345" version="567" priority="789"/> <cond desc="123" path="345" version="567" priority="789"/> <out where="333333"/> </rule> <rule> <cond desc="123" path="345" version="567" priority="789"/> <cond desc="123" path="345" version="567" priority="789"/> <out where="444444"/> </rule> </output> </root> chunli@Linux:~/boost$
Property Tree 解析JSON文件
chunli@Linux:~/boost$ cat test.json { "rate":{ "linktype":[0.8, 1.0, 1.0, 0.7, 0.4, 0.7, 0.8, 0.8, 0.9, 0.9, 0.4, 0.8, 1.0], "width":[[0.6, 0.8], [0.7, 0.87], [1.0, 1.2], [1.2, 1.4], [1.0, 1.0]], "use_toll":[0.33, 1.2] }, "turn_cost":{ "uturn":{ "Hturn":0, "triangle":1200, "normal":[1200, 300, 60, 5] } } } chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/json_parser.hpp> #include <boost/foreach.hpp> using namespace std; int main() { boost::property_tree::ptree pt; boost::property_tree::json_parser::read_json("test.json", pt); boost::property_tree::ptree child_linktype = pt.get_child("rate.linktype"); BOOST_FOREACH(boost::property_tree::ptree::value_type &vt, child_linktype) { cout << vt.second.get_value<double>() << " "; } cout << endl; return 0; } chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out 0.8 1 1 0.7 0.4 0.7 0.8 0.8 0.9 0.9 0.4 0.8 1 chunli@Linux:~/boost$
Property Tree 生成JSON文件
chunli@Linux:~/boost$ cat main.cpp #include <iostream> #include <string> #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/json_parser.hpp> #include <boost/foreach.hpp> using namespace std; using namespace boost::property_tree; int main(){ ptree pt_1,pt_11,pt_12; pt_11.put("id","3445"); pt_11.put<int>("age",29); pt_11.put("name","chen"); pt_12.push_back(make_pair("",pt_11)); pt_12.push_back(make_pair("",pt_11)); //replace or create child node "data" pt_1.put_child("data",pt_12); ostringstream os; write_json(os,pt_1); cout<<os.str()<<endl; return 0; } chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out { "data": [ { "id": "3445", "age": "29", "name": "chen" }, { "id": "3445", "age": "29", "name": "chen" } ] } chunli@Linux:~/boost$