C++primer第十章 关联容器

 关联容器和顺序容器的本质差别在于:关联容器通过键(key)存储和读取元素,而顺序容器则通过元素在容器中的位置顺序存储和访问元素。

  一般来说,如果希望有效地存储不同值的集合,那么使用 set 容器比较合适,而 map 容器则更适用于需要存储(乃至修改)每个键所关联的值的情况。在做某种文本处理时,可使用 set 保存要忽略的单词。而字典则是 map 的一种很好的应用:单词本身是键,而它的解释说明则是值。

  set 和 map 类型的对象所包含的元素都具有不同的键,不允许为同一个键添加第二个元素。如果一个键必须对应多个实例,则需使用 multimap 或 multiset,这两种类型允许多个元素拥有相同的键。

10.1. 引言:pair 类型

该类型在 utility 头文件中定义。

10.2. 关联容器

  关联容器共享大部分——但并非全部——的顺序容器操作。关联容器不提供front、 push_front、 pop_front、back、push_back 以及 pop_back 操作。

  顺序容器和关联容器公共的操作包括下面的几种:
  • 表 9.2 描述的前三种构造函数:

C<T> c; // creates an empty container
// c2 must be same type as c1
C<T> c1(c2); // copies elements from c2 into c1
// b and e are iterators denoting a sequence
C<T> c(b, e); // copies elements from the sequence into c

  关联容器不能通过容器大小来定义,因为这样的话就无法知道键所对应的值是什么。
  • 第 9.3.4 节中描述的关系运算。
  • 表 9.6 列出的 begin、end、rbegin 和 rend 操作。

  • 表 9.5 列出的类型别名(typedef)。注意,对于 map 容器,value_type并非元素的类型,而是描述键及其关联值类型的 pair 类型。第 10.3.2节 将详细解释 map 中的类型别名。
  • 表 9.11 中描述的 swap 和赋值操作。但关联容器不提供 assign 函数。
  • 表 9.10 列出的 clear 和 erase 操作,但关联容器的 erase 运算返回void 类型。
  • 表 9.8 列出的关于容器大小的操作。但 resize 函数不能用于关联容器。

  根据键排列元素

  “容器元素根据键的次序排列”这一事实就是一个重要的结论:在迭代遍历关联容器时,我们可确保按键的顺序的访问元素,而与元素在容器中的存放位置完全无关。

10.3. map 类型

  map 类型通常可理解为关联数组(associativearray):可使用键作为下标来获取一个值,正如内置数组类型一样。

10.3.1. map 对象的定义

  要使用 map 对象,则必须包含 map 头文件。在定义 map 对象时,必须分别指明键和值的类型(value type)(

map<string, int> word_count; // empty map from string to int

键类型的约束

  在使用关联容器时,它的键不但有一个类型,而且还有一个相关的比较函数。

  所用的比较函数必须在键类型上定义严格弱排序(strict weak ordering)。

10.3.2. map 定义的类型

  map 对象的元素是键-值对

  value_type 是存储元素的键以及值的 pair 类型,而且键为 const。

map 迭代器进行解引用将产生 pair 类型的对象

// get an iterator to an element in word_count
map<string, int>::iterator map_it = word_count.begin();
// *map_it is a reference to a pair<const string, int> object
cout << map_it->first; // prints the key for this element
cout << " " << map_it->second; // prints the value of the element
map_it->first = "new key"; // error: key is const
++map_it->second; // ok: we can change value through an iterator

对迭代器进行解引用将获得一个 pair 对象,它的 first 成员存放键,为const,而 second 成员则存放值。

10.3.3. 给 map 添加元素

  定义了 map 容器后,下一步工作就是在容器中添加键-值元素对。该项工作可使用 insert 成员实现;或者,先用下标操作符获取元素,然后给获取的元素赋值。

10.3.4. 使用下标访问 map 对象

map <string, int> word_count; // empty map
// insert default initialzed element with key Anna; then assign 1to 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 与使用下标访问数组或 vector 的行为截然不同:用下标访问不存在的元素将导致在 map 容器中添加一个新元素,它的键即为该下标值。

下标操作符返回值的使用

  有别于 vector 或 string 类型,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 的使用

键影响了实参的类型:插入单个元素的 insert 版本使用键-值 pair类型的参数。

  使用下标给 map 容器添加新元素时,元素的值部分将采用值初始化。通常,我们会立即为其赋值,其实就是对同一个对象进行初始化并赋值。而插入元素的另一个方法是:直接使用 insert 成员,其语法更紧凑:

// if Anna not already in word_count, inserts new element with value1
word_count.insert(map<string, int>::value_type("Anna", 1));

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

word_count.insert(make_pair("Anna", 1));

  或使用 typedef

typedef map<string,int>::value_type valType;
word_count.insert(valType("Anna", 1));

检测 insert 的返回值

  如果试图插入的元素所对应的键已在容器中,则 insert 将不做任何操作。含有一个或一对迭代器形参的 insert函数版本并不说明是否有或有多少个元素插入到容器中。

  带有一个键-值 pair 形参的 insert 版本将返回一个值:包含一个迭代器和一个 bool 值的 pair 对象,其中迭代器指向 map 中具有相应键的元素,而 bool 值则表示是否插入了该元素。如果该键已在容器中,则其关联的值保持不变,返回的 bool 值为 true。在这两种情况下,迭代器都将指向具有给定键的元素。

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 节)

使用 count 检查 map 对象中某键是否存在

int occurs = 0;
if (word_count.count("foobar"))
occurs = word_count["foobar"];

当然,在执行 count 后再使用下标操作符,实际上是对元素作了两次查找。如果希望当元素存在时就使用它,则应该用 find 操作。

读取元素而不插入该元素

int occurs = 0;
map<string,int>::iterator it = word_count.find("foobar");
if (it != word_count.end())
    occurs = it->second;

10.3.7. 从 map 对象中删除元素

  与顺序容器一样,可向 erase 传递一个或一对迭代器,来删除单个元素或一段范围内的元素。其删除功能类似于顺序容器,但有一点不同:map 容器的 erase 操作返回 void,而顺序容器的 erase 操作则返回一个迭代器,指向被删除元素后面的元素。

  除此之外,map 类型还提供了一种额外的 erase 操作,其参数是 key_type类型的值,如果拥有该键的元素存在,则删除该元素。

// erase of a key returns number of elements removed
if (word_count.erase(removal_word))
cout << "ok: " << removal_word << " removed\n";
else cout << "oops: " << removal_word << " not found!\n";

10.3.8. map 对象的迭代遍历

// get iterator positioned on the first element
map<string, int>::const_iterator
map_it = word_count.begin();
// for each element in the map
while (map_it != word_count.end()) {
    // print the element key, value pairs
    cout << map_it->first << " occurs "
    << map_it->second << " times" << endl;
    ++map_it; // increment iterator to denote the next element
}

10.3.9. “单词转换” map 对象

  下面的程序说明如何创建、查找和迭代遍历一个 map 对象.

  这个程序求解的问题是:给出一个 string 对象,把它转换为另一个 string 对象。本程序的输入是两个文件。第一个文件包括了若干单词对,每对的第一个单词将出现在输入的字符串中,而第二个单词则是用于输出。本质上,这个文件提供的是单词转换的集合——在遇到第一个单词时,应该将之替换为第二个单词。第二个文件则提供了需要转换的文本。如果单词转换文件的内容是:

  ‘em   them
  cuz   because
  gratz  grateful
  i       I
  nah    no

  pos    supposed
  sez      said
  tanx     thanks
  wuz      was

  而要转换的文本是:
  nah i sez tanx cuz i wuz pos to
  not cuz i wuz gratz
  则程序将产生如下输出结果:
  no I said thanks because I was supposed to
  not because I was grateful

单词转换程序

/*
* A program to transform words.
* Takes two arguments: The first is name of the word transformation
file
* The second is name of the input to transform
*/
int main(int argc, char **argv)
{
    // map to hold the word transformation pairs:
    // key is the word to look for in the input; value is word to use
    in the output
    map<string, string> trans_map;
    string key, value;
    if (argc != 3)
        throw runtime_error("wrongnumber of arguments");
        // open transformation file and check that open succeeded
    ifstream map_file;
    if (!open_file(map_file, argv[1]))
        throw runtime_error("no transformation file");
        // read the transformation map and build the map
     while (map_file >> key >> value)
        trans_map.insert(make_pair(key, value));
    // ok, now we‘re ready to do the transformations
    // open the input file and check that the open succeeded
    ifstream input;
    if (!open_file(input, argv[2]))
        throw runtime_error("no input file");
    string line; // hold each line from the input
    // read the text to transform it a line at a time
    while (getline(input, line)) {
        istringstream stream(line); // read the line a word at atime
        string word;
        bool firstword = true; // controls whether a space is printed
        while (stream >> word) {
        // ok: the actual mapwork, this part is the heart of the program
        map<string, string>::const_iterator map_it =
        trans_map.find(word);
        // if this word is in the transformation map
        if (map_it != trans_map.end())
        // replace it by the transformation value in the map
            word = map_it->second;
        if (firstword)
            firstword = false;
        else
            cout << " "; // print space between words
            cout << word;
        }
        cout << endl; // done with this line of input
    }
    return 0;
}

10.4. set 类型

  map 容器是键-值对的集合,好比以人名为键的地址和电话号码。相反地,set 容器只是单纯的键的集合

  • 第 10.2 节列出的所有通用的容器操作。
  • 表 10.3 描述的构造函数。
  • 表 10.5 描述的 insert 操作。
  • 表 10.6 描述的 count 和 find 操作。
  • 表 10.7 描述的 erase 操作。

10.4.1. set 容器的定义和使用

  为了使用 set 容器,必须包含 set 头文件。set 支持的操作基本上与 map提供的相同。

// define a vector with 20 elements, holding two copies of each number
//from 0 to 9
vector<int> ivec;
for (vector<int>::size_type i = 0; i != 10; ++i) {
    ivec.push_back(i); // duplicate copies of each number
}
// iset holds unique elements from ivec
set<int> iset(ivec.begin(), ivec.end());
cout << ivec.size() << endl; // prints 20
cout << iset.size() << endl; // prints 10

在 set 中添加元素

set<string> set1; // empty set
set1.insert("the"); // set1 now has one element
set1.insert("and"); // set1 now has two elements

另一种方法

set<int> iset2; // empty set
iset2.insert(ivec.begin(), ivec.end()); // iset2 has 10elements

从 set 中获取元素

  set 容器不提供下标操作符。为了通过键从 set 中获取元素,可使用 find运算。如果只需简单地判断某个元素是否存在,同样可以使用 count 运算,返回 set 中该键对应的元素个数。当然,对于 set 容器,count 的返回值只能是1(该元素存在)或 0(该元素不存在)

10.4.2. 创建“单词排除”集

  从 map 对象 word_count 中删除一个指定的单词。可将这个操作扩展为删除指定文件中所有的单词(即该文件记录的是排除集)。也即,我们的单词统计程序只对那些不在排除集中的单词进行统计。

  

void restricted_wc(ifstream &remove_file,
map<string, int> &word_count)
{
    set<string> excluded; // set to hold words we‘ll ignore
    string remove_word;
    while (remove_file >> remove_word)
        excluded.insert(remove_word);
    // read input and keep a count for words that aren‘t in theexclusion set
    string word;
    while (cin >> word)
    // increment counter only if the word is not in excluded
        if (!excluded.count(word))
            ++word_count[word];
}

10.5. multimap 和 multiset 类型

  map 和 set 容器中,一个键只能对应一个实例。而 multiset 和 multimap类型则允许一个键对应多个实例。例如,在电话簿中,每个人可能有单独的电话号码列表。在作者的文章集中,每位作者可能有单独的文章标题列表。

  multimap和 multiset 类型与相应的单元素版本具有相同的头文件定义:分别是 map 和set 头文件。

  multimap 和 multiset 所支持的操作分别与 map 和 set 的操作相同,只有一个例外:multimap 不支持下标运算

10.5.1. 元素的添加和删除  

由于键不要求是唯一的,因此每次调用 insert 总会添加一个元素。

// adds first element with key Barth
authors.insert(make_pair(
string("Barth, John"),
string("Sot-Weed Factor")));
// ok: adds second element with key Barth
authors.insert(make_pair(
string("Barth, John"),
string("Lost in the Funhouse")));

  带有一个键参数的 erase 版本将删除拥有该键的所有元素,并返回删除元素的个数

multimap<string, string> authors;
string search_item("Kazuo Ishiguro");
// erase all elements with this key; returns number of elements removed
multimap<string, string>::size_type cnt =
authors.erase(search_item);

10.5.2. 在 multimap 和 multiset 中查找元素

  在 multimap 中,同一个键所关联的元素必然相邻存放

使用 find 和 count 操作

  使用 find 和 count 可有效地解决刚才的问题。count 函数求出某键出现的次数,而 find 操作则返回一个迭代器,指向第一个拥有正在查找的键的实例:

// author we‘ll look for
string search_item("Alain de Botton");
// how many entries are there for this author
typedef multimap<string, string>::size_type sz_type;
sz_type entries = authors.count(search_item);
// get iterator to the first entry for this author
multimap<string,string>::iterator iter =
authors.find(search_item);
// loop through the number of entries there are for this author
for (sz_type cnt = 0; cnt != entries; ++cnt, ++iter) cout <<
    iter->second << endl; // print each title

与众不同的面向迭代器的解决方案

  另一个更优雅简洁的方法是使用两个未曾见过的关联容器的操作:lower_bound 和 upper_bound。

// definitions of authors and search_item as above
// beg and end denote range of elements for this author
typedef multimap<string, string>::iterator authors_it;
authors_it beg = authors.lower_bound(search_item),
end = authors.upper_bound(search_item);
// loop through the number of entries there are for this author
while (beg != end) {
    cout << beg->second << endl; // print each title
    ++beg;
}

enual_range 函数

  解决上述问题更直接的方法是:调用 equal_range 函数来取代调用 upper_bound 和 lower_bound 函数。equal_range 函数返回存储一对迭代器的 pair 对象。如果该值存在,则 pair 对象中的第一个迭代器指向该键关联的第一个实例,第二个迭代器指向该键关联的最后一个实例的下一位置。如果找不到匹配的元素,则 pair 对象中的两个迭代器都将指向此键应该插入的位置。

// definitions of authors and search_item as above
// pos holds iterators that denote range of elements for this key
pair<authors_it, authors_it>
pos = authors.equal_range(search_item);
// loop through the number of entries there are for this author
while (pos.first != pos.second) {
    cout << pos.first->second << endl; // print each title
    ++pos.first;
}

10.6. 容器的综合应用:文本查询程序

  我们的程序将读取用户指定的任意文本文件,然后允许用户从该文件中查找单词。查询的结果是该单词出现的次数,并列出每次出现所在的行。如果某单词在同一行中多次出现,程序将只显示该行一次。行号按升序显示,即第 7 行应该在第 9 行之前输出,依此类推。

10.6.1. 查询程序的设计

  设计程序的一个良好习惯是首先将程序所涉及的操作列出来。明确需要提供的操作有助于建立需要的数据结构和实现这些行为。从需求出发,我们的程序需要支持如下任务:

  1. 它必须允许用户指明要处理的文件名字。程序将存储该文件的内容,以便输出每个单词所在的原始行。

  2. 它必须将每一行分解为各个单词,并记录每个单词所在的所有行。在输出行号时,应保证以升序输出,并且不重复。
  3. 对特定单词的查询将返回出现该单词的所有行的行号。
  4. 输出某单词所在的行文本时,程序必须能根据给定的行号从输入文件中获取相应的行

数据结构

  我们将用一个简单的类 TextQuery 实现这个程序。再加几种容器的配合使用,就可相当巧妙地满足上述要求。
  1. 使用一个 vector<string> 类型的对象存储整个输入文件的副本。输入文件的每一行是该 vector 对象的一个元素。因而,在希望输出某一行时,只需以行号为下标获取该行所在的元素即可。
  2. 将每个单词所在的行号存储在一个 set 容器对象中。使用 set 就可确保每行只有一个条目,而且行号将自动按升序排列。
  3. 使用一个 map 容器将每个单词与一个 set 容器对象关联起来,该 set容器对象记录此单词所在的行号。
  综上所述,我们定义的 TextQuery 类将有两个数据成员:储存输入文件的vector 对象,以及一个 map 容器对象,该对象关联每个输入的单词以及记录该单词所在行号的 set 容器对象。

操作

  对于类还要求有良好的接口。然而,一个重要的设计策略首先要确定:查询函数需返回存储一组行号的 set 对象。这个返回类型应该如何设计呢?

  事实上,查询的过程相当简单:使用下标访问 map 对象获取关联的 set 对象即可。唯一的问题是如何返回所找到的 set 对象。安全的设计方案是返回该set 对象的副本。但如此一来,就意味着要复制 set 中的每个元素。如果处理的是一个相当庞大的文件,则复制 set 对象的代价会非常昂贵。其他可行的方法包括:返回一个 pair 对象,存储一对指向 set 中元素的迭代器;或者返回set 对象的 const 引用。为简单起见,我们在这里采用返回副本的方法,但注意:如果在实际应用中复制代价太大,需要新考虑其实现方法。

  第一、第三和第四个任务是使用这个类的程序员将执行的动作。第二个任务则是类的内部任务。将这四任务映射为类的成员函数,则类的接口需提供下列三个 public 函数:

  • read_file 成员函数,其形参为一个 ifstream& 类型对象。该函数每次从文件中读入一行,并将它保存在 vector 容器中。输入完毕后,read_file 将创建关联每个单词及其所在行号的 map 容器。
  • run_query 成员函数,其形参为一个 string 类型对象,返回一个 set 对象,该 set 对象包含出现该 string 对象的所有行的行号。

  • text_line 成员函数,其形参为一个行号,返回输入文本中该行号对应的文本行。

  无论 run_query 还是 text_line 都不会修改调用此函数的对象,因此,可将这两个操作定义为 const 成员函数(第 7.7.1 节)。为实现 read_file 功能,还需定义两个private 函数来读取输入文本和创建 map 容器:
  • store_file 函数读入文件,并将文件内容存储在 vector 容器对象中。
  • build_map 函数将每一行分解为各个单词,创建 map 容器对象,同时记录每个单词出现行号。

10.6.2. TextQuery 类

class TextQuery {
public:
    // typedef to make declarations easier
    typedef std::vector<std::string>::size_type line_no;
    /* interface:
    * read_file builds internal data structures for the given file
    * run_query finds the given word and returns set of lines on
    which it appears
    * text_line returns a requested line from the input file
    */
    void read_file(std::ifstream &is)
    { store_file(is); build_map(); }
    std::set<line_no> run_query(const std::string&) const;
    std::string text_line(line_no) const;
private:
    // utility functions used by read_file
    void store_file(std::ifstream&); // store input file
    void build_map(); // associated each word with a set of line
    numbers
    // remember the whole input file
    std::vector<std::string> lines_of_text;
    // map word to set of the lines on which it occurs
    std::map< std::string, std::set<line_no> > word_map;
};

10.6.3. TextQuery 类的使用

// program takes single argument specifying the file to query
int main(int argc, char **argv)
{
    // open the file from which user will query words
    ifstream infile;
    if (argc < 2 || !open_file(infile, argv[1])) {
        cerr << "No input file!" << endl;
        return EXIT_FAILURE;
    }
    TextQuery tq;
    tq.read_file(infile); // builds query map
    // iterate with the user: prompt for a word to find and print results
    // loop indefinitely; the loop exit is inside the while
    while (true) {
        cout << "enter word to look for, or q to quit: ";
        string s;
        cin >> s;
        // stop if hit eof on input or a ‘q‘is entered
        if (!cin || s == "q") break;
        // get the set of line numbers on which this word appears
        set<TextQuery::line_no> locs = tq.run_query(s);
        // print count and all occurrences, if any
        print_results(locs, s, tq);
    }
    return 0;
}
时间: 2024-10-16 05:43:20

C++primer第十章 关联容器的相关文章

【足迹C++primer】38、关联容器操作(2)

关联容器操作(2) map的下标操作 map的下标操作 map和unordered_map容器提供了下标运算符合一个对应的at函数 对于一个map使用下标操作,其行为与数组或vector上的下标操作很不相同: 使用一个不再容器中的关键字作为下标,会添加一个此关键字的元素到map中 map和unordered_map的下标操作 c[k] 返回关键字为k的元素,如果关键字k不再c中,添加一个关键字为k的元素,对其进行值初始化 c.at(k) 访问关键字为k的元素,带参数检测,如果k不再c重那么返回一

【足迹C++primer】37、关联容器概述

关联容器概述 关联容器不支持顺序容器的位置操作,如push_back或push_front 也不支持构造函数或插入操作这些接受一个元素值和一个数量值的操作. 定义关联容器 这里注意哦,我这是一个函数,里面关联容器map是包含在头文件map中的!!! 还有就是set是包含在头文件set中的,string是包含在头文件string中的!!! //关联容器初始化 void fun1() { map<string, size_t> word_count; //空容器 //列表初始化 set<st

【足迹C++primer】36、使用关联容器

使用关联容器 两个主要的关联容器map和set 8个容器:(1)或者是一个set一个map:(2)或者要求不重复的关键字,或者允许重复关键字: (3)按顺序保存元素,或无序保存.允许重复关键字的容器的名字中都包含单词multi:不 保持关键字按顺序存储的容器的名字都以单词unordered开头. map类型常常被叫成关联容器,这个是关键字查找 set就是全由关键字组成 这次写博客的时候有点晚,早上有考试,没办法,不然挂了那就 咳咳,还有现在我发现一个写好博客的好方法了,我不在边写博客边看书了,感

【足迹C++primer】38、关联容器操作(1)

关联容器操作 关联容器中还定义了三个类型,如下: set<string>::value_type v1; //这个v1是string类型 set<string>::key_type v2; //这个v2是string类型 map<string, int>::value_type v3; //v3是pair类型pair<const string, int> map<string, int>::key_type v4; //v4是string类型 m

C++ Primer笔记7_STL之关联容器

关联容器 与顺序容器不同,关联容器的元素是按关键字来访问和保存的.而顺序容器中的元素是按他们在容器中的位置来顺序保存的. 关联容器最常见的是map.set.multimap.multiset map的元素以键-值[key-value]对的形式组织:键用作元素在map中的索引,而值则表示所存储和读取的数据. set仅包含一个键,并有效的支持关于某个键是否存在的查询. pair类型 首先介绍下pair,pair定义在utility头文件中,一个pair保存两个数据成员,类似容器,pair是一个用来生

0717-----C++Primer听课笔记----------STL之关联容器

1.Map 1.1 map<K, V>是一种pair的容器,pair的种类是pair<K, V>.map采用下标访问一个已存在的key, 会更新value,访问map中不存在的元素时,会增加一个新的键值对.map中的元素按照key进行从小到大排列.map的底层实现是采用二叉树,一般是使用红黑树. #include <iostream> #include <string> #include <map> using namespace std; /*

c++ primer(第五版)学习笔记及习题答案代码版(第十一章)关联容器

笔记较为零散,都是自己不熟悉的知识点. 习题答案至于一个.cc 中,包含Chapter7.h头文件,读入文件包括./test ./rules .需要演示某一题直接修改 #define NUM****, 如运行11.23题为#define NUM1123: chapter 11 1.  关联容器不支持顺序容器的位置相关的操作,例如push_front或push_back.原因是关联容器中元素是根据关键字存储的,这些操作对 关联容器没有意义.而且关联容器也不支持构造函数或插入操作这些接收一个元素值和

《C++primer》v5 第11章 关联容器 读书笔记 习题答案

11.1 map是关联容器,vector是顺序容器 11.2 略 11.3 int main() { map<string,int> word; string s; while(cin>>s) word[s]++; for(auto i:word) cout<<i.first<<" "<<i.second<<endl; return 0; } 11.4 void convers(string &s) { s

c++ primer 10 关联容器

关联容器和顺序容器的本质差别在于:关联容器通过键(key)存储和读取元素,顺序容器则通过元素在容器中的位置顺序存储和访问元素 关联容器类型 map 关联数组:元素通过键来存储和读取 set 大小可变的集合,支持通过键实现的快速读取 multimap 支持同一个键多次出现的 map 类型 multiset 支持同一个键多次出现的 set 类型 pair类型 pair是一种模版类型,在创建pair对象,必须提供两个类型名. 头文件 utility pairs 类型提供的操作 pair<T1, T2>