第十章

10.3

        map 是键-值对的集合。map 类型通常可理解为关联数组(associativearray) :可使用键作为下标来获取一个值,正如内置数组类型一样。而关联的本质在于元素的值与某个特定的键相关联, 而并非通过元素在数组中的位置来获取。

        在使用关联容器时, 它的键不但有一个类型, 而且还有一个相关的比较函数。默认情况下,标准库使用键类型定义的 < 操作符来实现键(key type)的比较。 在实际应用中,键类型必须定义 < 操作符,而且该操作符应能”正确地工作”,这一点很重要。

        value_type 是存储元素的键以及值的 pair 类型,而且键为 const ,key_type在 map 容器中,用做索引的键的类型,mapped_type在 map 容器中,键所关联的值的类型在学习 map 的接口时,需谨记 value_type 是 pair 类型,它的值成员可以修改,但键成员不能修改。 

10.3.4. 使用下标访问 map 对象
         如下编写程序时: 
map <string, int> word_count; // empty map
// insert default initialzed element with key Anna; then assign 1 to its value
word_count["Anna"] = 1;
        将发生以下事情:
1. 在 word_count 中查找键为 Anna 的元素,没有找到。
2. 将一个新的键-值对插入到 word_count 中。它的键是 const string 类型的对象, 保存 Anna。 而它的值则采用值初始化, 这就意味着在本例中值为 0。
3. 将这个新的键-值对插入到 word_count 中。

4. 读取新插入的元素,并将它的值赋为 1。使用下标访问 map 与使用下标访问数组或 vector 的行为截然不同:用下标访问不存在的元素将导致在 map 容器中添加一个新元素,它的键即为该下标值

下标行为的编程意义 
         对于 map 容器,如果下标所表示的键在容器中不存在,则添加新元素,这一特性可使程序惊人地简练: 
// count number of times each word occurs in the input
map<string, int> word_count; // empty map from string to int
string word;
while (cin >> word)
    ++word_count[word];
10.3.5. map::insert 的使用


m.insert(e)                            
e 是一个用在 m 上的 value_type 类型的值。如果键 (e.first)不在 m 中,则插入一个值为 e.second 的新元素; 如果该键在 m 中已存在,则保持 m 不变。该函数返回一个 pair 类型对象,包含指向键为 e.first 的元素的 map 迭代器,以及一个 bool 类型的对象,表示是否插入了该元素


m.insert(beg,end)                                          
beg 和 end 是标记元素范围的迭代器,其中的元素必须为 m.value_type 类型的键-值对。对于该范围内的所有元素, 如果它的键在 m 中不存在, 则将该键及其关联的值插入到 m。 返回 void 类型
m.insert(iter,e)e 是一个用在 m 上的 value_type 类型的值。如果键 (e.first)不在 m 中,则创建新元素,并以迭代器 iter 为 起点搜索新元素存储的位置。返回一个迭代器,指向 m 中具 有给定键的元素
word_count.insert(map<string, int>::value_type("Anna", 1));

        这是一个新创建的 pair 对象,将直接插入到 map 容器中。谨记 value_type是 pair<const K, V> 类型的同义词,K 为键类型,而 V 是键所关联的值的类型。

传递给 insert 的实参相当笨拙。可用两种方法简化:使用 make_pair:

word_count.insert(make_pair("Anna", 1));
typedef map<string,int>::value_type valType;
word_count.insert(valType("Anna", 1));
检测 insert 的返回值
         insert 版本将返回一个值:包含一个迭代器和一个 bool 值的 pair 对象,其中迭代器指向 map 中具有相应键的元素,而 bool 值则表示是否插入了该元素。如果该键已在容器中,则其关联的值保持不变,返回的 bool 值为false。 
// count number of times each word occurs in the input
map<string, int> word_count;                     // empty map from string to int string word;
while (cin >> word) {
// inserts element with key equal to word and value 1;
// if word already in word_count, insert does nothing
pair<map<string, int>::iterator, bool> ret =word_count.insert(make_pair(word, 1));
if (!ret.second)                                 // word already in word_count
++ret.first->second;                             // increment counter
}
10.3.6. 查找并读取 map 中的元素
map<string,int> word_count;
int occurs = word_count["foobar"];
         使用下标存在一个很危险的副作用:如果该键不在 map 容器中,那么下标操作会插入一个具有该键的新元素 
         map 容器提供了两个操作:count 和 find,用于检查某个键是否存在而不会插入该键。 
m.count(k)返回 m 中 k 的出现次数
m.find(k)如果 m 容器中存在按 k 索引的元素,则返回指向该元素的迭代器。如果不存在,则返回超出末端迭代器(第 3.4 节)
         如果希望当具有指定键的元素存在时,就获取该元素的引用,否则就不在容器中创建新元素,那么应该使用 find。 

10.3.7. 从 map 对象中删除元素
         map容器的erase操作返回void,而顺序容器的 erase 操作则返回一个迭代器,指向被删除元素后面的元素。
         除此之外,map 类型还提供了一种额外的 erase 操作,其参数是 key_type类型的值,如果拥有该键的元素存在,则删除该元素。 erase 函数返回被删除元素的个数。对于 map 容器,该值必然是 0 或 1。如果返回 0,则表示欲删除的元素在 map 不存在。 

10.4

        set 容器只是单纯的键的集合 两种例外包括:set 不支持下标操作符,而且没有定义 mapped_type 类型。在 set 容器中,value_type 不是 pair 类型,而是与 key_type 相同的类型。它们指的都是 set 中存储的元素类型。这一差别也体现了 set 存储的元素仅仅是键,而没有所关联的值。与 map 一样,set 容器存储的键也必须唯一,而且不能修改。 

        与 map 容器的操作一样,带有一个键参数的 insert 版本返回 pair 类型对象, 包含一个迭代器和一个 bool 值, 迭代器指向拥有该键的元素, 而 bool 值表明是否添加了元素。使用迭代器对的 insert 版本返回 void 类型。 

        正如不能修改 map 中元素的键部分一样,set 中的键也为 const。在获得指向 set 中某元素的迭代器后,只能对其做读操作,而不能做写操作: 

// set_it refers to the element with key == 1
set<int>::iterator set_it = iset.find(1);
*set_it = 11; // error: keys in a set are read-only
cout << *set_it << endl; // ok: can read the key

10.5.2

m.lower_bound(k)返回一个迭代器,指向键不小于 k 的第一个元素
m.upper_bound(k)返回一个迭代器,指向键大于 k 的第一个元素
m.equal_range(k)返回一个迭代器的 pair 对象 它的 first 成员等价于 m.lower_bound(k)。而 second 成 员则等价于 m.upper_bound(k)

        若该键没有关联的元素,则 lower_bound 和 upper_bound 返回相同的迭代器:都指向同一个元素或同时指向 multimap 的超出末端位置。它们都指向在保持容器元素顺序的前提下该键应被插入的位置 

/*      10.26-29      */
#include<iostream>
#include<string>
#include<map>
#include<fstream>
#include<sstream>

using namespace std;

int main()
{
	multimap<string,string> author;
	string author_name,book_name;
	ifstream open_file("text.txt");
	if(!open_file)
	{
		cout<<"can't open it"<<endl;
		return 0;
	}
	string line;
	while(getline(open_file,line))
	{
		istringstream is(line);
		while(is>>author_name)
		{
			while(is>>book_name)
			author.insert(make_pair(author_name,book_name));
		}
	}

	cout<<"input the author you want to delete:";
	string erase_name;
	cin>>erase_name;
	pair<multimap<string,string>::iterator,multimap<string,string>::iterator> iter=author.equal_range(erase_name);
	if(iter.first==iter.second)
		cout<<"can't find "<<erase_name<<endl;
	else
		author.erase(iter.first,iter.second);

	multimap<string,string>::iterator pre,cur;
	pre=cur=author.begin();

	for(;cur!=author.end();)
	{
		if(cur==author.begin())
			cout<<"Author Names Beginning with '"<<(cur->first)[0]<<"':"<<endl;

		if((cur->first)[0]!=(pre->first)[0])
			cout<<"Author Names Beginning with '"<<(cur->first)[0]<<"':"<<endl;
		pair<multimap<string,string>::iterator,multimap<string,string>::iterator> ret=author.equal_range(cur->first);
		cout<<ret.first->first;
		for(;ret.first!=ret.second;ret.first++)
			cout<<","<<ret.first->second;
		cout<<endl;

		pre=cur;
		cur=ret.second;
	}

	getchar();
	getchar();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值