c++primer第五版第十一章练习

11.1

map是关键字-值的储存,关键字是唯一的,通过下标运算符访问关键字对应的值,默认储存顺序是按照关键字

vector储存的是对象,通过下标运算符访问对应的对象,储存顺序按照添加顺序


11.2

list 用在需要频繁的插入或删除元素

vector 在需要索引访问时

deque 由于是先进先出,用在一些消息内容上

map 像字典之类的

set 用于检测是否含有


11.3

这个该了一下,变成统计字母

#include <iostream>
#include <map>
#include <set>
#include <string>
#include <fstream>
int main(int argc, char **argv)
{
	using namespace std;
	ifstream ifile(argv[1]);
	if (!ifile)
	{
		cerr << "open file error!";
		exit(1);
	}
	map<char, size_t> letter;		//统计字母数量
	set<char> exclude{ ',', '<', '.', '>', '/', '?', ';', ':', '\'', '"', '[', '{', ']', '}', '\\', '|', '*', '-', '=', '+', '_', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')' };
	char temp;
	while (ifile >> temp)
	{
		if(exclude.find(temp)==exclude.cend())
		<span style="white-space:pre">	</span>++letter[temp];
	}
	for (auto x : letter)
		cout << x.first << "\t" << x.second << endl;
	return 0;
}

11.4

#include <iostream>
#include <map>
#include <set>
#include <string>
#include <fstream>
#include <cctype>
int main(int argc, char **argv)
{
	using namespace std;
	ifstream ifile(argv[1]);
	if (!ifile)
	{
		cerr << "open file error!";
		exit(1);
	}
	map<char, size_t> letter;
	set<char> exclude{ ',', '<', '.', '>', '/', '?', ';', ':', '\'', '"', '[', '{', ']', '}', '\\', '|', '*', '-', '=', '+', '_', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')' };
	char temp;
	while (ifile >> temp)
	{
		if (exclude.find(temp) == exclude.end())	//如果没有在其中找到temp		or isalpha(temp); 当不是字母时返回0、小写2、大写1
			++letter[tolower(temp)];	//把temp放进letter中,如果已存在则对应计数+1,否则先创建并让对应计数设置为1		tolower返回小写
	}
	for (auto x : letter)
		cout << x.first << "\t" << x.second << endl;
	return 0;
}

11.5

set的元素类型是关键字

map的元素类型是 关键字-值 组合

11.6

set是关联容器

list是顺序容器

关联容器不支持像push_back、push_front之类的操作,因为储存是按照关键字来储存的


11.7

#include <iostream>
#include <vector>
#include <map>
#include <string>
int main()
{
	using namespace std;
	map<string, vector<string>> msv;
	string temp,t;
	cout << "enter Familys name:";
	cin >> temp;
	while (cin)
	{
		while (cin)
		{
			cout << "enter Family:";
			cin >> t;
			msv[temp].push_back(t);		//下标为temp对应的vector把t添加进入容器
		}
		cin.clear();
		cout << "enter Familys name:";
		cin >> temp;
	}
	cin.clear();

	for (auto &x : msv)
	{
		cout << x.first << ":" << endl;
		for (auto &a : x.second)		//输出当前关键字对应的vector的内容
			cout << a << "\t";
		cout << endl;
	}
	system("pause");
	return 0;
}

11.8

#include <iostream>
#include <vector>
#include <string>
bool isnot(std::vector<std::string> &v,std::string &s);
int main()
{
	using namespace std;
	vector<string> word;
	string temp;
	while (cin >> temp)
	{
		if (isnot(word, temp))
			word.push_back(temp);
	}
	for (auto &x : word)
		cout << x << "\t";
	system("pause");
	return 0;
}
bool isnot(std::vector<std::string> &v, std::string &s)
{
	for (auto &x : v)
	{
		if (x == s)
			return false;
	}
	return true;
}
set的关键字不允许重复,所以不用花费外的代码来检查


11.9

map<string,list<int>> m

#include <iostream>
#include <fstream>
#include <map>
#include <list>
#include <string>
#include <set>
#include <sstream>
#include <cctype>
#include <algorithm>
int main(int argc, char **argv)
{
	using namespace std;
	ifstream ifile(argv[1]);
	if (!ifile)
	{
		cerr << "open file error!";
		exit(1);
	}
	map<string, list<int>> msl;
	string word;
	string temp;
	int line=1;
	while (getline(ifile,word))					//读取一行
	{
		istringstream iss(word);				//关联到行
		while (iss >> temp)					//读取字符串
		{
			if (ispunct(temp[temp.size() - 1]))		//去除标点符号
				temp.erase(temp.size()-1,1);
			if (isupper(temp[0]))				//转换为小写开头
				temp[0] = tolower(temp[0]);
			/*if (find(msl[temp].begin(), msl[temp].end(), line) == msl[temp].begin())
				msl[temp].push_back(line);*/
			bool b = true;
			for (auto x : msl[temp])			//检查行号是否出现过(单词第一次在当前行号)
			{
				if (x == line)
				{
					b = false;
					break;
				}
			}
			if (b)
				msl[temp].push_back(line);
		}
		++line;
	}
	for (auto &x : msl)
	{
		cout << x.first;
		if (x.first.size() <= 7)
			cout << "\t";
		cout << "\tin line: ";
		for (auto a : x.second)
			cout << a << "\t";
		cout << endl;
	}
	return 0;
}

11.10

可以,因为有定义运算符"<"

11.11

using func=bool(const Sales_data &,const Sales_data &);

multiset<Sales_data,func*> bookstore(compareIsbn);


11.12

#include <iostream>
#include <vector>
#include <string>
#include <utility>		//pair

int main()
{
	using namespace std;
	vector<pair<string, int>> vpsi;
	string tstr;
	int tint;
	while (cin>>tstr>>tint)
	{
		vpsi.push_back({ tstr, tint });		//vpsi.push_back(pair<string, int>(tstr, tint));
	}
	for (auto &x : vpsi)
	{
		cout << x.first << "\t" << x.second << endl;
	}
	system("pause");
	return 0;
}

11.13

vec.push_back(pair<string,int>(str,i));

vec.push_back({str,i});

vec.push_back(make_pair(str,i));


vec.emplace_back(...↑...);

最好理解的是vec.push_back(pair<string,int>(str,i));,一眼就看到实参类型

最易于编写的是vec.push_back({str,i});,重复使用时不用大幅度变动代码


11.14

#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <utility>	//pair
int main()
{
	using namespace std;
	map<string, vector<pair<string,string>>> msv;
	string temp,n,b;
	cout << "enter Familys name:";
	cin >> temp;
	while (cin)
	{
		while (cin)
		{
			cout << "enter name and birth:";
			cin >> n >> b;
			msv[temp].push_back({ n, b });		//为家庭temp添加新成员
		}
		cin.clear();
		cout << "enter Familys name:";
		cin >> temp;
	}
	cin.clear();

	for (auto &x : msv)
	{
		cout << x.first << ":" << endl;
		for (auto &a : x.second)		//输出当前关键字对应的vector的内容
			cout << a.first << "\t" << a.second << endl;
		cout << endl;
	}
	system("pause");
	return 0;
}

11.15

mapped_type:vector<int>

key_type:int

value_type:pair<int,vector<int>>


11.16

cin>>map_it->second;


11.17

第二个非法,因为c对象是multiset类型,该类型没有push_back方法


11.18

map<string,int>::const_iterator iter=count_cbegin();


11.19

multiset<Sales_data, bool(*)(const Sales_data &, const Sales_data &)> bookstore(isfun);
multiset<Sales_data, bool(*)(const Sales_data &, const Sales_data &)>::iterator iter = bookstore.begin();

11.20

本节的方法更易于阅读

#include <iostream>
#include <map>
#include <set>
#include <string>
#include <fstream>
int main(int argc, char **argv)
{
	using namespace std;
	ifstream ifile(argv[1]);
	if (!ifile)
	{
		cerr << "open file error!";
		exit(1);
	}
	map<char, size_t> letter;		//统计字母数量
	set<char> exclude{ ',', '<', '.', '>', '/', '?', ';', ':', '\'', '"', '[', '{', ']', '}', '\\', '|', '*', '-', '=', '+', '_', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')' };
	char temp;
	while (ifile >> temp)
	{
		auto iter = letter.insert({ temp, 1 });
		if (iter.second)
			++iter.first->second;
	}
	for (auto x : letter)
		cout << x.first << "\t" << x.second << endl;
	return 0;
}

11.21

相当于++word_count[word];

++word_count.insert({word,0}).first.second;

调用insert会返回一个pair<iterator,bool>,iterator指向刚刚插入的元素,所以.first->second就是说刚刚插入的元素的值

所以就是把关键字word的值++


11.22

参数类型为:pair<string,vector<int>>

返回类型为:pair<map<string,vector<int>>::iterator,bool>


11.23

#include <iostream>
#include <vector>
#include <map>
#include <string>
int main()
{
	using namespace std;
	map<string, multimap<string,string>> msv;
	string temp, f, l;
	cout << "enter Familys name:";
	cin >> temp;
	while (cin)
	{
		while (cin)
		{
			cout << "enter first last:";
			cin >> f >> l;
			if (!cin)			//如果输入错误或输入结束,退出到输入家庭,否当输入结束符时,f和l依然会被赋值到msv
				break;
			msv[temp].insert({ f, l });
		}
		cin.clear();
		cout << "enter Familys name:";
		cin >> temp;
	}
	cin.clear();

	for (auto &x : msv)
	{
		cout << x.first << ":" << endl;
		for (auto &a : x.second)
			cout << a.first << " " << a.second << endl;
		cout << endl;
	}
	system("pause");
	return 0;
}

11.24

把关键字为0的值设为1,不存在就先创建然后设置


11.25

把第一个元素的值设为0


11.26

map的关键字

关键字对应的值

例如map<char,int> sel{{a,1},{b,2},{c,3},{d,5}};

sel[b]返回的就是2


11.27

需要统计同一关键字存在的数目时

需要确定关键字是否存在时


11.28

map<string,vector<int>>::iterator iter=m.find("***");

或者是auto iter=m.find("...");


11.29

upper_bound和lower_bount会指向同一个位置

equal_rabge返回一个pair<iter,iter>,pair的两个元素都指向一个相同的位置


11.30

因为pos是equal_range返回的一个pair对象,所以first是指向一个multimap,

所以意思是pos的第一个元素指向的multimap对象的第2个元素


11.31

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

int main()
{
	using namespace std;
	multimap<string, string> mss;
	string author,title;
	while (cin)
	{
		cout << "enter author and title:";
		cin >> author>>title;
		if (!cin)
		{
			cin.clear();
			break;
		}
		mss.insert({ author, title });
	}
	cout << "enter erase author and title:";
	author = title = "";
	cin.clear();
	cin >> author>>title;
	auto iter = mss.find(author);
	auto c = mss.count(author);
	/*while ((iter=mss.find(author)) != mss.cend())
	{
	if (iter->second == title)
	mss.erase(iter);
	}*/
	while (c)
	{
		if (iter->second == title)
		{
			mss.erase(iter);					//删除书本,自动把iter指向下一个,无需++
			break;
		}
		++iter;
		--c;
	}
	for (auto &x : mss)
	{
		cout << x.first << " " << x.second << endl;
	}
	system("pause");
	return 0;
}

11.32

#include <iostream>
#include <string>
#include <map>
#include <set>
int main()
{
	using namespace std;
	multimap<string, string> mss;
	string author, title;
	while (cin)
	{
		cout << "enter author and title:";
		cin >> author >> title;
		if (!cin)
		{
			cin.clear();
			break;
		}
		mss.insert({ author, title });
	}
	map<string, multiset<string>> msms;	//multiset会排序
	for (auto &x : mss)
		msms[x.first].insert(x.second);
	for (auto &x : msms)
	{
		for (auto &a : x.second)
			cout << x.first << "\t" << a << endl;
	}
	system("pause");
	return 0;
}

11.33

#include <iostream>
#include <fstream>
#include <sstream>
#include <set>
#include <map>
std::map<std::string, std::string> buildmap(std::ifstream &ifile)	//初始化map
{
	std::map<std::string, std::string> temp;
	std::string str,f,s;
	while (getline(ifile, str))
	{
		std::istringstream sst(str);
		sst >> f >> s;
		temp[f] = s;		//把暗文对应的明文设置
	}
	return temp;
}
std::string trans(const std::string &s, std::map<std::string, std::string> &m)//转换
{
	auto temp = m.find(s);
	if (temp != m.end())	//如果是暗文
		return m[s];		//返回暗文对应的明文
	else
		return s;
}
int main(int argc,char **argv)
{
	using namespace std;
	ifstream ifpw(argv[1]), iftxt(argv[2]);
	if (!ifpw&&!iftxt)
	{
		cerr << "open file error!\n";
		exit(1);
	}
	map<string, string> pw(buildmap(ifpw));	//初始化密码文件
	string temp,f;
	while (getline(iftxt, temp))
	{
		istringstream iss(temp);
		while (iss >> f)
		{
			cout << trans(f, pw) << " ";	//输出f的明文(如果f是暗文)
		}
		cout << endl;
	}
	system("pause");
	return 0;
}

或者书的:

#include <iostream>
#include <string>
#include <map>
#include <fstream>
#include <sstream>
using namespace std;

map<string, string> buildMap(ifstream &map_file)
{
	map<string, string> trans_map;
	string key, value;
	while (map_file >> key>>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]), infile(argv[2]);
	if (!map_file || !infile)
	{
		cerr << "open file error!\n";
		exit(1);
	}
	word_transform(map_file, infile);
	return 0;
}

11.34

错误,transform的map形参是const 的,下标运算符返回的是引用


11.35

使用trans_map[key]时,当赋值出现重复的关键字时,该关键字对应的值为最后一关键字的值

使用insert时,当检查到trans_map里已经存在该关键字,则不进行插入,所以该关键字对应的值为第一次成功插入关键字时的值


11.36

当只有一个关键字和空格时,key会读取关键字,那么剩下的空格就交给的getline读取到了value中,因为value只有一个空格,所以size为1,if条件不成立,转交给else

所以会触发异常:throw runtime_error("no rule for "+key);


11.37

没有明显的排序、有时应用程序维护元素的顺序的代价是非常高昂的,这时使用无序会好一点

无序容器提供了与有序容器相同的操作,无序容器也允许有重复关键字的版本


11.38

#include <iostream>
#include <string>
#include <fstream>
#include <unordered_map>
#include <unordered_set>
int main(int argc, char **argv)
{
	using namespace std;
	ifstream ifile(argv[1]);
	if (!ifile)
	{
		cerr << "open file error!";
		exit(1);
	}
	unordered_map<char, size_t> letter;	
	unordered_set<char> exclude{ ',', '<', '.', '>', '/', '?', ';', ':', '\'', '"', '[', '{', ']', '}', '\\', '|', '*', '-', '=', '+', '_', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')' };
	char temp;
	while (ifile >> temp)
	{
		if (exclude.find(temp) == exclude.cend())
			++letter[temp];
	}
	for (auto x : letter)
		cout << x.first << "\t" << x.second << endl;
	return 0;
}



#include <iostream>
#include <string>
#include <unordered_map>
#include <fstream>
#include <sstream>
using namespace std;

unordered_map<string, string> buildMap(ifstream &map_file)
{
	unordered_map<string, string> trans_map;
	string key, value;
	while (map_file >> key>>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 unordered_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]), infile(argv[2]);
	if (!map_file || !infile)
	{
		cerr << "open file error!\n";
		exit(1);
	}
	word_transform(map_file, infile);
	return 0;
}





2015年11月25日20:24:35

以后在搞懂无序容器是什么鬼

今天以为亲人离世了,心情有点






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值