一.Map
1.前言
在程序中,经常会遇见关联的数据对出现,可以把这个数据对中的一个称作索引值,另外一个称作关联值或映射值,假如索引值是整数的时候,可以采用数组或者向量存储这些数据对,但是假如索引值是其他的任意数据类型的时候,就需要用到map了
2.使用map
#include <map>
map <string, string> addresses;
<1>添加元素
map中的第一个元素用于存放索引值,第二个元素用于存放映射值,为了对某一个索引值添加对应的映射元素,可以使用下标操作符,如对于上面定义的通信录addresses,要添加元素,可以如下:
addresses["kfqcome"]="kfqcome@gmail.com";
假如map中已经包含了某一键值(索引值),则后面对这一键值添加元素将不会起作用,即map中每个键值只可以对应于一个映射值,如:
addresses["kfqcome"]="justin@gmail.com";
这句代码将不会起作用
<2>查找
要查找某个键值已经存在,可以使用find函数,有两种重载版本
iterator find(const key_type& k);
const_iterator find(const key_type& k) const;
对于上面的addresses的map对象,要查找键值为"kfqcome"的键值是否存在,可以使用如下的代码:
map<string,string>:: const_iterator iter=addresses.find(“kfqcome”);
if (iter ==addresses.end())
cout << "didn’t find" << endl;
else
cout << iter ->first << ''/t'' << iter ->second << endl;
iter->first输出的数据对的键值,iter->second输出的数据对的对应的映射值
<3>取数据
使用下标操作符加键值就可以取出对应的映射值
map[key]
二.tuple
1.前言
在c++中,相同函数名和相同参数的函数不能进行重载去返回不同类型的值,平常的做法定义两个名字相近的函数来达到这个目的。
假设需要实现这样一个函数:将某个文件名转换为FILE * 和文件描述符,函数名和参数都相同,只是返回类型不同
int convert_filename(const char* path);
FILE* convert_filename(const char* path); //出错
现在假如能够对这个函数包装需要返回的两种类型的数据,就可以十分方便的实现这个功能,tuple可以做到。
虽然说对于一些这样的问题可以自己定义一些结构体可以完成,但是tuple毕竟是已经开发完成的标准库,除了封装类型外还有许多其他的功能,在常规开发中可以节省许多时间,何乐而不为呢?
2.使用tuple
Tuple是一个大小固定的异构对象集合,即tuple可以包含任意类型的多个数据,目前标准的库支持0-10个元素的tuple,假如vs环境中没有安装到tuple库,可以自己下载boost库,它里面包含了tuple库
<1>基本方法
使用tuple的例子:
#include "boost/tuple/tuple.hpp"
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
boost::tuple<int,double,std::string>triple(42,3.14,"The amazing tuple!");
int i=boost::tuples::get<0>(triple); //i=42
double d=triple.get<1>(); //d=3.14
std::string s=boost::get<2>(triple);
return 0;
}
同时对于1中的那个文件名转换函数,可以将其写成:
typedef tuple<int, FILE *> file_t;
file_t convert_filename(const char* path);
<2>make_tuple函数
可以使用make_tuple函数来创建tuple对象,如:
boost::tuple<int,double,std::string> t = boost::make_tuple(123,3.14159,"kk");
三.Multimap
前面看到map对于一个键值只能存放一个与其对应的映射值,但是实际的应用中,经常会碰到一个键值对应多个映射值的情况,比如一个人可以有多个手机号码,或者有多个电子邮箱等。
<1> 构造函数
multimap<Key, Data, Compare, Alloc>
Key:键值的类型
Data:multimap的数据类型
Compare:键值的比较函数,函数使用两个参数,参数的类型就是键值的类型,如果第一个参数的值小于第二参数的值,则返回true,否则返回false
Alloc:内存分配器,用于内部的内存管理
<2> 添加和查询
前面的map是采用下标操作符来添加和获取数据对,但是对于multimap,用下标操作符来添加数据对也许可以,但是用下标来获取则会出现问题,因为一个键值可以对应多个映射值,使用下标操作符取的话就难以去确定选择哪个映射值。基于这个原因,标准库设计者不采用下标来进行这些操作,而是设计另外的函数。
添加元素:insert,使用pair类型作为参数
multimap<string,string> dns;
dns.insert(make_pair("192.168.1.19","www.kfqcome.com"));
dns.insert(make_pair("192.168.1.19","kfqcome.com"));
dns.insert(make_pair("192.168.1.19","www.kfqcome.org"));
(1)查询单个值
find,使用键值作为参数
find 函数定义
iterator find(const key_type& k);
const_iterator find(const key_type& k) const;
find查询得到的迭代器指向这个键值与它的第一个映射值
使用举例:
iter=dns.find("192.168.1.19");
if(iter!=dns.end())
{
printf("has found/n");
}
else
{
printf("haven't found/n");
}
(2)查询某键值对应的映射值的个数
count,使用键值作为参数
int num=dns.count("192.168.1.19");//num=3
(3)查找某键值的下界和上界对应的元素
某键值的下界是指multimap中与这个键值相等或者比这个键值大一级元素。
某键值的上界是指multimap中比这个键值大一级的元素
multimap<string,string> dns;
dns.insert(make_pair("192.168.1.19","www.kfqcome.com"));
dns.insert(make_pair("192.168.1.19","kfqcome.com"));
dns.insert(make_pair("192.168.1.15","www.kfqcome.info"));
dns.insert(make_pair("192.168.1.19","www.kfqcome.org"));
dns.insert(make_pair("192.168.1.1","www.vision.com"));
typedef multimap<string,string>::iterator MIT;
pair<MIT,MIT> range=dns.equal_range("192.168.1.1");
MIT lowIter=range.first;
MIT upperIter=range.second;
cout<<"low range of key "<< lowIter->first<<":"<<lowIter->second<<endl;
cout<<"upper range of key" <<upperIter->first<<":" << upperIter->second <<endl;
输出的结果为是:
low range of key 192.168.1.1:www.vision.com
upper range of key192.168.1.15:www.kfqcome.info
注意:如果查找的键值已经是multimap最大的,那么它的上界会为空
使用这个可以获得有相同键值的所有映射值,如下:
multimap<int,string> courses;
courses.insert(make_pair(1,"math"));
courses.insert(make_pair(2,"computer science"));
courses.insert(make_pair(2,"programming"));
courses.insert(make_pair(4,"electronics"));
courses.insert(make_pair(6,"biology"));
typedef multimap<int,string>::iterator MIT;
pair<MIT,MIT> range=courses.equal_range(2);
MIT lowIter=range.first;
MIT upperIter=range.second;
MIT iter;
for(iter=lowIter;iter!=upperIter;)
{
cout<<"key "<<iter->first<<": "<<iter->second<<endl;
++iter;
}
输出的结果为:
key 2: computer science
key 2: programming