c++ primer(第五版)学习笔记及习题答案代码版(第十一章)关联容器
chapter 11
1. 关联容器不支持顺序容器的位置相关的操作,例如push_front或push_back。原因是关联容器中元素是根据关键字存储的,这些操作对关联容器没有意义。而且关联容器也不支持构造函数或插入操作这些接收一个元素值和一个数量值的操作。其中,关联容器的迭代器都是双向的。
传递给平【排序算法的可调用对象必须满足与关联容器中关键字一样的类型要求。
2. 为了使用自己定义的操作,在定义multiset时我们必须提供两个类型:关键字类型sales_data,以及比较操作类型--应该是一种函数指针
类型,指向comparaisbn.
multiset
bookstore(compareisbn);
当用decltype来获得一个函数指针类型时,必须加上一个*来指出我们要使用一个给定函数类型的指针。
3. 与其他标准库类型不同,pair的数据成员是public的。两个成员分别是first和second。
对于set类型,key_type和value_type是一样的,set中保存的就是关键字。map中元素是关键字-值对,即每个元素是一个pair对象,包含一个关键字和一个关联的值。由于不能改变一个元素的关键字,因此这些pair的关键字部分是const:
与顺序容器一样使用作用域运算符来提取一个类型的成员: map
只有map类型(unordered_map,unordered_multimap,map)才定义了mapped_type。
要记住,一个map的value_type是一个pair,我们可以改变pair的值,但不能改变关键字成员的值。
4. 由于map和set(以及对应的无序元素)包括不重复的关键字,因此插入一个已存在的元素对容器没有任何影响、
auto ret =word_count.insert({word, 1});
ret保存insert返回的值,是一个pair; ret.first是pair的第一个成员,是一个map的迭代器,指向具有给定关键字的元素。
ret.first -> 解引用此迭代器,提取map中的元素,元素也是一个pair。
5. 一个给定的关键字只能出现一次。这样任意给定的单词只有一个关联的计数器。而在mutil容器的关键字不必唯一。
erase操作与对应的顺序容器的操作非常相似:指定的元素被删除,函数返回void。
对一个map使用下标操作,其行为与数组或vector上的下标操作很不相同: 使用一个不在容器中的关键字作为下标,会添加一个具有此
关键字的元素到map中。
map的下标运算符与我们用过的其他下标运算符的另一个不同是返回类型。通常,解引用一个迭代器与下标运算符返回的类型是一样的。
但对map则不然:当对一个map进行下标操作时,会获得一个mapped_type对象,当解引用一个map迭代器时,会得到一个value_type对象。
map下标返回一个左值,所以我们既可以读也可以写元素。
6. set
iset.find(11); //当11超过iset大小时,返回的迭代器,其值等于iset.end()
lower_bound 和upper_bound不适用于无序容器,下标和at操作只适用于非const的map和unorderd_map。
如果一个multimap或multiset中有多个元素具有给定关键字,则这些元素在容器中会相邻存储。
c.equal_range(k); 返回一个迭代器pair,表示关键字等于k的元素的范围,若k不存在,pair的两个成员均等于c.end()。
7. lower_bound返回的迭代器可能指向一个具有给定关键字的元素,但也可能不指向。如果关键字不再容器中,则lower_bound
会返回关键字的第一个安全插入点--不影响容器中元素的插入位置。
无序关联容器不是使用比较运算符来组织元素,而是使用一个哈希函数和关键字类型的==运算符。在关键字类型的元素没有明显的序关系的
情况下,无序容器是非常有用的。unordered_map/ordered_set。
brb be right back k okay? y why r are u you pic picture thk thanks! l8r later
where r u y dont u send me a pic k thk l8r
//chapter7.h #ifndef chapter7_h #define chapter7_h #include #include using namespace std; class sales_data; istream &read(istream &is, sales_data &item); class sales_data { friend sales_data add(const sales_data &lhs, const sales_data &rhs); friend istream &read(istream &is, sales_data &item); friend ostream &print(ostream &os, const sales_data &item); public: // sales_data(){}; sales_data(const string &s, unsigned n, double p): bookno(s), units_sold(n), revenue(p){ cout <<"sales_data(const string &, unsigned, double)" << endl; } sales_data(){ cout << "sales_data()" << endl; } /* sales_data() : sales_data("", 0, 0.0f){ cout << "sales_data()" << endl; } */ sales_data(const string &s):bookno(s), units_sold(0), revenue(0.0){ cout << "sales_data(const string& s)"<> item.bookno >> item.units_sold >> price; item.revenue = price * item.units_sold; return is; } ostream &print(ostream &os, const sales_data &item){ os << item.isbn() << " " << item.units_sold << " " <> p.name >> p.address; if(!is) p = person(); return is; } ostream &print(ostream &os, const person &p){ os << p.getname() << p.getaddress(); return os; } //class screen class screen; class window_mgr{ public: typedef vector::size_type screenindex; inline void clear(screenindex); private: vector screens; }; class screen{ friend void window_mgr::clear(screenindex); public: typedef string::size_type pos; screen(){} screen(pos ht, pos wd): height(ht), width(wd), contents(ht * wd, ' ') { } screen(pos ht, pos wd, char c): height(ht), width(wd), contents(ht * wd, c){} char get(){ return contents[cursor]; } char get(pos r, pos c) const { return contents[r * width + c]; } inline screen &set(char c); inline screen &set(pos r, pos c, char ch); inline screen &move(pos r, pos c); const screen &display(ostream &os) const{ os << contents; return *this; } pos size() const; private: pos cursor; pos height, width; string contents; }; screen::pos screen::size() const{ return height * width; } inline screen &screen::set(char c){ contents[cursor] = c; return *this; } inline screen &screen::set(pos r, pos col, char ch){ contents[r * width + col] = ch; return *this; } inline screen &screen::move(pos r, pos c){ pos row = r * width + c; cursor = row + c; return *this; } //class account class account{ public: account(){} account(string &s, double m): owner(s), amount(m){} void calculate(){ amount += amount * interestrate; } static double rate() { return interestrate; } static void rate(double newrate){ interestrate = newrate;} private: string owner; double amount; static double interestrate; static constexpr double todayrate = 3.65; static double initrate(){ return todayrate; } }; #endif
//main.cc #include #include #include #include #include #include #include #include #include #include #include #include #include "chapter7.h" using namespace std; #define num1138 /*11.11*/ bool compareisbn(sales_data& lhs, sales_data& rhs){ return lhs.isbn() < rhs.isbn(); } /*11.33*/ map buildmap(ifstream& map_file){ map trans_map; for(string key, value; map_file >> key && getline(map_file, value); ) if(value.size() > 1) trans_map[key] = value.substr(1); // trans_map.insert({key, value.substr(1)}); return trans_map; } const string& transform(const string &s, const map &m){ /*11.34*/ // auto key = m[s]; auto map_it = m.find(s); if(map_it != m.end()) return map_it -> second; // map_it 是const_interator类型,返回值类型加const else return s; } void word_transform(ifstream &map_file, ifstream& input){ auto trans_map = buildmap(map_file); cout << "transformation: "<first << " " <<" value: "<< entry-> second << endl; } cout << "\n\n"; for(string text; getline(input, text); ){ istringstream iss(text); for(string word; iss >> word; ){ cout << transform(word, trans_map) <<" "; } cout << endl; } } /*11.38*/ void word_transform(){ ifstream ifs_map("./rules"), ifs_content("./test"); if(ifs_map && ifs_content){ unordered_map trans_map; for(string key, value; ifs_map >> key && getline(ifs_map, value); ) if(value.size() > 1) trans_map[key] = value.substr(1); for(string text, word; getline(ifs_content, text); cout <> word; ){ auto map_it = trans_map.find(word); cout << (map_it == trans_map.end() ? word : map_it->second)<< " "; } } else cerr << "can't find the documents. "< > family; string lastname, firstname; for(cout << "please input last name: "; cin >> lastname && lastname != "exit";){ for(cout << "please input first name: "; cin >> firstname && firstname != "exit";) family[lastname].push_back(firstname); cout << "please input last name: "< > " "返回类型: pair::iterator, bool>"< families; string lastname; string firstname; for(; cin >> firstname >> lastname; families.insert({lastname, firstname})) //or insert(make(lastname, firstname)) ; for(auto &i : families) cout << i.second << " "<< i.second < m; m[0] = 1; for (const auto& e : m) std::cout << e.first << " " << e.second << "\n"; cout << "赋值操作. "< v; v[0] = 1; cout <<"vec: "< m = {{1, "linux"}, {2, "c++"}}; map::key_type type_to_subscript = 1; map::mapped_type type_to_return = map[type_to_subscript]; #endif /*11.27*/ #ifdef num1127 cout << "对于允许存在重复元素的multimap和multiset用count,对于只有unique元素的map用find."<> m; m = {{"alan", {1, 2, 3, 4, 5, }}, {"john", {1, 5, 6, 7, 8}}}; map>::iterator it; // type used to define this iterator. it = m.find("alan"); cout << it -> second[2] < mm{ {"cc","dd"}, {"gg","hh"}, {"aa", "bb"},{"cc","dd1"}}; for(auto &i : mm) cout << i.first <<" "<< i.second << endl; string author = "cc"; string word = "dd"; auto found = mm.find(author); mm.erase(found); cout << "*******this is apart line******"< mm{ {"cc","dd"}, {"gg","hh"}, {"aa", "bb"},{"cc","dd1"}}; map> order_mm; for(auto & author : mm) order_mm[author.first].insert(author.second); for(auto &author : order_mm){ cout << author.first << ": "; for(auto &work : author.second) cout << work << " "; cout << endl; } #endif /*11.33*/ #ifdef num1133 ifstream ifs_map("./rules"), ifs_content("./test"); if (ifs_map && ifs_content) word_transform(ifs_map, ifs_content); else std::cerr << "can't find the documents." << std::endl; #endif /*11.34*/ #ifdef num1134 cout << "在上一题中修改演示报错, 因为map的迭代器并没有声明为const类型,但是m被声明为const的map类型,如果插入新的pair元素,就会出错. "< word_count; for(string word; cin >> word; ++word_count[word]) ; for(auto &i : word_count) cout << i.first << " occurs: " << i.second \ << (i.second > 1 ? " times" : "time" )<
上一篇: c++11实现一个半同步半异步线程池
下一篇: JS中的BOM操作解析