C++Prime 第十一章
练习11.1
map以关键字来存储和访问,vector以元素在容器中的位置来存储和访问.
练习11.2
list: 插入&删除,如链表中间插入一个数据
vector: 随机访问,
deque: 头尾插删,
map: 关键字存储,如字典
set:关键字的集合.如判断一个元素是否在集合中出现过
练习11.3
map<string, size_t> word_count;
string word;
while (cin >> word)
++word_count[word];
for (const auto& w : word_count)
cout << w.first << "occurs " << (w.second << (w.second > 1) ? "times" : "time")<< endl;
练习11.4
int main()
{
map<string, size_t> word_count;
string word;
while (cin >> word)
{
if (isupper(word[0]))//大小写
word[0] = tolower(word[0]);
if (ispunct(word[word.size() - 1]))//标点
word.erase(word.size() - 1);
++word_count[word];
}
for (const auto& w : word_count)
cout << w.first << " occurs " << w.second << ((w.second > 1) ? " times" : " time")<< endl;
return 0;
}
练习11.5
最大的区别是map的关键字关联到一个值,而set的值就是关键字本身.需要集合类型时选择set,需要存储多余信息时选择map
练习11.6
set的值不重复,且有序.
练习11.7
int main()
{
map<string, vector<string> > m;
string tmp;
cout << "Please enter first name (q to quit):\n";
while (cin >> tmp && tmp != "q")
{
cout << "Please enter child name (q to quit):\n";
while (cin >> tmp && tmp != "q")
m[tmp].push_back(tmp);
cout << "Please enter first name (q to quit):\n";
}
return 0;
}
练习11.8
自动排序,单词不重复则不会丢失单词.查找快速.
练习11.9
int main()
{
map<string, list<int> > m;
istream_iterator<string> sin(cin), send;
while (sin != send)
{
istream_iterator<int> in(cin), end;
copy(in, end, inserter(m[*sin], m[*sin].begin()));
}
return 0;
}
练习11.10
vector迭代器可以直接比较大小,但是要求所有的map中的迭代器指向同一个vector,否则还是报错.
list迭代器不可以用作关键字,因为不可以直接比较大小.
练习11.11
方法一:重载<运算符.
方法二:参考P.223,定义函数指针.
//使用decltype(fun) * 来指定函数指针
//使用using声明
using F = bool(*)(const Test& , const Test& );
set<Test, F> m(compareIsbn);
//最普通的方法
set<Test, bool(*)(const Test&, const Test&)> m1(compareIsbn);
//使用typedef
typedef bool(*pf)(const Test&, const Test&) ;
set<Test,pf> m2(compareIsbn);
//typedef + decltype
typedef decltype(compareIsbn)* pf2;
set<Test, pf2> m2(compareIsbn);
练习11.12
int main()
{
vector<pair<string, int> >a;
string tmp;
while (cin>>tmp)
{
int num;
cin >> num;
a.push_back({ tmp,num });
}
for_each(a.begin(), a.end(), [](const pair<string, int>& p) {cout << p.first << " " << p.second << endl; });
return 0;
}
练习11.13
make_pair,
{},
pair<string,int>("sf",2),
emplace_back("string",12)
练习11.14
OK
练习11.15
mapped_type 是映射的值类型,即vector<int>
key_type 是关键字类型,即int
value_type 是pair<int,vector<int>>
练习 11.16
int main()
{
map<string, int> m{ {"hello",1},{"world",2} };
auto p = m.begin();
while (p != m.end())
{
if (p->first == "hello")
p->second = 100;
p++;
}
for (const auto& x : m)
cout << x.first << " " << x.second << endl;
}
练习11.17
第二个调用不合法,关联容器的push_back操作是违法的,无意义.
练习11.18
pair<string,size_t>::iterator
练习11.19
multiset<Sales_data, decltype(compareIsbn)* >::const_iterator = bookstore.begin();
练习11.20
int main()
{
map<string, size_t> word_count;
string word;
while (cin >> word)
{
auto ret = word_count.insert({ word,1 });
if (!ret.second)
++ret.first->second;
}
for (const auto& w : word_count)
cout << w.first << "occurs " << (w.second << (w.second > 1) ? "times" : "time") << endl;
}
练习11.21
单词计数
练习11.22
pair<string,vector<int> >;//插入
pair<map<string,vector<int> >::iterator,bool );//返回
练习11.24
将m中关键字为0的元素(如果存在,这里肯定不存在,空map)它的映射的值变为1,如果不存在,则创建一个pair<0,1>.
练习11.25
v的首元素变为1,v为空vector,所以直接报错.
练习11.26
关键字的类型key_type可以用做下标.
返回的类型是映射的值的类型mapped_type.
map<string,int > m;
string可以用来下标操作,返回int
练习11.27
需要统计有多少个元素在容器中时,可以选择count
练习11.28
map<string, vector<int> >m;
map<string, vector<int> >::iterator p = m.find("dsf");
练习11.29
lower_bound 和 upper_bound 都指向关键字可以插入的位置,equal_range返回一个pair,两个成员函数同指向关键字可以插入的位置.
练习11.30
pos是一个pair对象,其first成员是个迭代器,迭代器的second指向题目
练习11.31
int main()
{
multimap<string, string> m;
m.insert({ "zhang","math" });
m.insert({ "zhang","english" });
m.insert({ "liu","math" });
m.insert({ "zhang","chinese" });
m.insert({ "zhao","ecology" });
auto p = m.find("zhang");
auto n = m.count("zhang");
while (n)
{
if (p->second == "english")
{
m.erase(p);
break;
}
++p;
--n;
}
}
练习11.32
int main()
{
multimap<string, string> m;
m.insert({ "zhang","math" });
m.insert({ "zhang","english" });
m.insert({ "liu","math" });
m.insert({ "zhang","chinese" });
m.insert({ "zhao","ecology" });
auto p = m.find("zhang");
auto n = m.count("zhang");
while (n)
{
if (p->second == "english")
{
m.erase(p);
break;
}
++p;
--n;
}
for (auto it = m.begin(); it != m.end(); ++it)
{
cout << it->first << " "<<it->second<<endl;
}
return 0;
}
练习11.33
map<string, string> buildMap(ifstream& map_file)
{
map<string, string> trans_map;
string key;
string value;
while (map_file >> key && getline(map_file, value))
{
if (value.size() > 1)
trans_map[key] = value.substr(1);
else
throw runtime_error("no rule for " + key);
}
return trans_map;
}
const string& transform(const string& s, const map<string, string>& m)
{
auto map_it = m.find(s);
if (map_it != m.cend())
return map_it->second;
else
return s;
}
void word_transform(ifstream& map_file, ifstream& input)
{
auto trans_map = buildMap(map_file);
string text;
while (getline(input, text))
{
istringstream stream(text);
string word;
bool firstword = true;
while (stream >> word) {
if (firstword)
firstword = false;
else
cout << " ";
cout << transform(word, trans_map);
}
cout << endl;
}
}
练习11.34
会报错.因为map是const的,而下标运算企图改变map
练习11.35
下标运算每次都会更新值,insert不会更新
练习11.36
抛出异常.
练习11.37
无序版本避免了让大量数据变得有序而带来的消耗
有序版本让关键字有序
练习11.38
加油