C++ Primer课后习题解答(第十一章)

Exercises Section 11.1

Ex11.1

map:关联容器,元素为键值对;map没有push_back;map的元素按照关键字来保存和访问
vector:顺序容器,元素为内置类型或者自定义类型;可以对vector调用排序算法;vector是按照元素在容器的位置保存和访问

Ex11.2

list:在任何位置添加和删除元素
vector:随机访问,只能在尾部添加元素
deque:随机访问,只能在首尾添加元素
map:键值对的集合
set:关键字即为值

Ex11.3

#include<iostream>
#include<map>

using namespace std;

int main()
{
    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;
    system("pause");
    return 0;
}

Ex11.4

#include<iostream>
#include<map>
#include<string>

using namespace std;

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.pop_back();
        ++word_count[word];
    }
    for (const auto &w : word_count)
        cout << w.first << " occurs " << w.second << ((w.second > 1) ? "times" : "time") << endl;
    system("pause");
    return 0;
}

Exercises Section 11.2.1

Ex11.5

map:保存的元素为键值对,需要使用关键字查找值时使用 map
set:保存的元素为关键字,关键字也即是值

Ex11.6

set:关联容器,可以判断给定的值是否存在
list:顺序容器,可以顺序访问元素

Ex11.7

#include<iostream>
#include<map>
#include<vector>

using namespace std;

void add_family(map<string, vector<string>> &families, const string &family)
{
    if (families.find(family) == families.end())
        families[family] = vector<string>();
}

void add_kid(map<string, vector<string>> &families, const string &family, const string kid)
{
    families[family].push_back(kid);
}

int main()
{
    map<string, vector<string>> families;
    add_family(families, "Smith");
    add_kid(families, "Smith", "John");
    for (const auto &f : families)
    {
        cout << f.first << ": ";
        for (const auto &c : f.second)
            cout << c << " ";
        cout << endl;
    }
    system("pause");
    return 0;
}

Ex11.8

// vector 需要判断是否有重复元素而 set 不需要
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int main()
{
    vector<string> words;
    string word;
    while (cin >> word)
    {
        if (find(words.cbegin(), words.cend(), word) == words.cend())   
            words.push_back(word);
    }
    for (const auto &w : words)
        cout << w << " ";
    cout << endl;
    system("pause");
    return 0;
}

Exercises Section 11.2.2

Ex11.9

#include<iostream>
#include<map>
#include<list>

using namespace std;

int main()
{
    map<string, list<int>> word_line;
    string word;
    int number;
    while (cin >> word >> number)
        word_line[word].push_back(number);
    for (const auto &w : word_line)
    {
        cout << w.first << " ";
        for (const auto &c : w.second)
            cout << c << " ";
        cout << endl;
    }
    system("pause");
    return 0;
}

Ex11.10

map的关键字必须支持 < 操作,vector 支持 < 操作,故而可以定义 vector<int>::iterator 到 int 的 map;
而 list 不支持 < 操作,故而不能定义 list<int>::iterator 到 int 的 map

Ex11.11

typedef bool(*pf)(const Sales_data &, const Sales_data &);
multiset<Sales_data, pf> bookstore(compareIsbn);

Exercises Section 11.2.3

Ex11.12

#include<iostream>
#include<utility>
#include<vector>

using namespace std;

int main()
{
    vector<pair<string, int>> vec;
    string word;
    int num;
    while (cin >> word >> num)
        vec.push_back(make_pair(word, num));
    for (const auto &v: vec)
        cout << v.first << " " << v.second << endl;
    system("pause");
    return 0;
}

Ex11.13

#include<iostream>
#include<utility>

using namespace std;

int main()
{
    pair<string, int> p1("Hello", 1);
    pair<string, int> p2 = {"world", 2};
    pair<string, int> p3 = make_pair("astral", 3);
    cout << p1.first << " " << p1.second << endl;
    cout << p2.first << " " << p2.second << endl;
    cout << p3.first << " " << p3.second << endl;
    system("pause");
    return 0;
}

Ex11.14

#include<iostream>
#include<map>
#include<vector>
#include<utility>

using namespace std;

void add_family(map<string, vector<pair<string, string>>> &families, const string &family)
{
    if (families.find(family) == families.end())
        families[family] = vector<pair<string, string>>();
}

void add_kid(map<string, vector<pair<string, string>>> &families, const string &family, const pair<string, string> kid)
{
    families[family].push_back(kid);
}

int main()
{
    map<string, vector<pair<string, string>>> families;
    add_family(families, "Smith");
    add_kid(families, "Smith", make_pair("John", "1995-11-11"));
    add_kid(families, "Smith", make_pair("Mike", "1996-12-12"));
    add_family(families, "Mikse");
    for (const auto &f : families)
    {
        cout << f.first << ": ";
        for (const auto &c : f.second)
            cout << c.first << "," << c.second << " ";
        cout << endl;
    }
    system("pause");
    return 0;
}

Exercises Section 11.3.1

Ex11.15

map<int, vector<int>> map

mapped_type: vector<int>
key_type: int
value_type: pair<const int, vector<int>>

Ex11.16

#include<iostream>
#include<map>

using namespace std;


int main()
{
    map<string, int> map = {{"Hello", 1}, {"World", 2}};
    auto it = map.begin();
    it->second = 2;
    for (const auto &m : map)
        cout << m.first << " " << m.second << endl;
    system("pause");
    return 0;
}

Ex11.17

multiset<string> c;
vector<string> v;

// set 容器只允许读取元素,故前两个非法,后两个合法
copy(v.begin(), v.end(), inserter(c, c.end()));	
copy(v.begin(), v.end(), back_inserter(c));
copy(c.begin(), c.end(), inserter(v, v.end()));
copy(c.begin(), c.end(), back_inserter(v));

Ex11.18

pair<const string, size_t>::iterator map_it = word_count.cbegin();

Ex11.19

multiset<Sales_data, decltype(compareIsbn)*> bookstore(compareIsbn);
pair<const Sales_data, decltype(compareIsbn)*> iter = bookstore.begin();

Exercises Section 11.3.2

Ex11.20

#include<iostream>
#include<map>

using namespace std;

int main()
{
    map<string, size_t> word_count;
    string word;
    while (cin >> word)
    {
        auto it = word_count.insert({word, 1});
        if (!it.second)
            ++it.first->second;
    }
    for (const auto &w : word_count)
        cout << w.first << " occurs " << w.second << ((w.second > 1) ? "times" : "time") << endl;
    system("pause");
    return 0;
}

Ex11.21

while (cin >> word)
	++word_count.insert({word, 0}).first->second;
    
// word_count.insert({word, 0})返回一个 pair 类型, pair.first是一个迭代器,指向具有指定关键字的元素,即word_count.insert({word, 0}).first 的类型为 pair<const string, size_t>::iterator
// word_count.insert({word, 0}).first->second即为 size_t 类型,若元素不在 map 中,则计数值为1;若在,则增1

Ex11.22

c.insert(v);
参数 v 的类型:value_type型对象,即 pair<const string, vector<int>>
返回类型:pair<map<string, vecotr<int>>::iterator, bool>

Ex11.23

#include <iostream>
#include <map>
 
using namespace std;
 
void add_kid(multimap<string, string> &families, const string &family, const string &kid)
{
	families.insert({family, kid});
}
 
int main()
{
	multimap<string, string> families;
 
	add_kid(families, "Li", "Jim");
	add_kid(families, "Li", "Jack");
	add_kid(families, "Wang", "Lucy");
 
	for (const auto &f : families) 
    {
		cout << f.first << ": " << f.second << endl;
	}
    system("pause");
	return 0;
}

Exercises Section 11.3.4

Ex11.24

// 将关键字为0的元素的值赋值为1,如果没有则创建
map<int, int> m;
m[0] = 1;

Ex11.25

cpp

// 非法;v 是一个空容器,容器越界
vector<int> v;
v[0] = 1;

Ex11.26

#include<iostream>
#include<map>

using namespace std;

int main()
{
    map<string, int> word_count;
    string word;
    while (cin >> word)
        ++word_count[word];
    for (const auto &w : word_count)
        cout << w.first << " " << w.second << endl;
    system("pause");
    return 0;
}

Exercises Section 11.3.5

Ex11.27

当想要知道关键字 k 的元素数量时,使用 count(k)
当想要知道容器中是否有关键字 k 对应的元素存在时,使用 find(k)

Ex11.28

#include<iostream>
#include<map>
#include<vector>

using namespace std;

int main()
{
    vector<int> v1 = {1, 2, 3, 4, 5};
    vector<int> v2 = {6, 7, 8, 9, 10};
    string s1 = "T";
    string s2 = "G";
    map<string, vector<int>> m = {{s1, v1}, {s2, v2}};
    auto it = m.find("T");
    cout << (*it).first << " ";
    for (const auto &i : it->second)
        cout << i << " ";
    cout << endl;
    system("pause");
    return 0;
}

Ex11.29

如果给定关键字不在容器中,lower_bound 和 upper_bound 会返回相等的迭代器,指向一个不影响排序的关键字的插入位置;equal 的两个迭代器都指向关键字可以插入的位置

Ex11.30

pos.first->second:pos 是一个迭代器 pair,两个迭代器分别指向查找元素的第一个位置与最后一个查找元素之后的位置;pos.first指向第一个迭代器,解引用为其关键字,然后调用 second 为其关键字对应的值。

Ex11.31

#include<iostream>
#include<map>

using namespace std;

int main()
{
    multimap<string, string> authors;
    string s1, s2;
    string book{"Alice"};
    while (cin >> s1 >> s2)
    {
        authors.insert({s1, s2});
    }
    authors.erase(book);
    for (const auto &c : authors)
        cout << c.first << " " << c.second << endl;
    system("pause");
    return 0;
}

Ex11.32

#include<iostream>
#include<map>

using namespace std;

int main()
{
    multimap<string, string> authors;
    string s1, s2;
    string book{"Alice"};
    while (cin >> s1 >> s2)
    {
        authors.insert({s1, s2});
    }
    auto it = authors.find(book);
    for (; it->first == book;)
        it = authors.erase(it);
    for (const auto &c : authors)
        cout << c.first << " " << c.second << endl;
    system("pause");
    return 0;
}

Exercises Section 11.3.6

Ex11.33

#include <iostream>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <map>
 
using namespace std;
 
map<string, string> buildMap(ifstream &map_file)
{
	map<string, string> trans_map;
	string key, 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;
	}
}
 
 
int main(int argc, char *argv[])
{
	ifstream map_file(argv[1]);
	ifstream text(argv[2]);
	
	word_transform(map_file, text);
	
	return 0;
}

Ex11.34

使用下标替换 find,如果容器中不存在查找的关键字,那么就会使用值初始化方法构造一个 pair 放入容器中。

Ex11.35

当关键字不在 map 中,使用 insert 和使用下标没有区别;
当关键字在 map 中时,使用下标会用新值覆盖原有值,而 insert 会返回一个值指出插入失败。

Ex11.36

buildMap 函数会使用 value.size() 检查单词是否存在,如果不存在,则抛出一个异常。
posted @   astralcon  阅读(25)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示