12、C++ Primer 4th 笔记,关联容器(2)

1map set 容器中,一个键只能对应一个实例。multimapmultiset类型允许一个键对应多个实例。其支持的操作分别与mapset的操作相同,只有一个例外,multimap不支持下标运算。setmultiset专门用于存储键。

2、关联容器 map set 的元素是按顺序存储的。而 multimap multset 也一样。因此,在 multimap multiset 容器中,如果某个键对应多个实例,则这些实例在容器中将相邻存放。迭代遍历 multimap multiset 容器时,可保证依次返回特定键所关联的所有元素。

3、在multimapmultiset中寻找元素时,一般有以下三种方法:

1)使用 find count count 函数求出某键出现的次数,而 find 操作则返回一个迭代器,指向第一个拥有正在查找的键的实例。

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 的超出末端位置。它们都指向在保

持容器元素顺序的前提下该键应被插入的位置。

4、一个查找文本的例子

#include "map"
#include "set"
#include "vector"
#include "string"
#include "fstream"
#include "iostream"
#include "sstream"
using namespace std;

class TextQuery
{
public:
	typedef std::vector<std::string>::size_type line_no;
	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:
	void store_file(std::ifstream&); //存储文件
	void build_map(); //将每个单词与相关联的行号建立映射
	std::vector<std::string> lines_of_text; //存储原文件的每一行
	std::map< std::string, std::set<line_no> > word_map; //映射结构
};

void TextQuery::store_file(std::ifstream &is)
{
	string textline;
	while(getline(is, textline))
	{
		lines_of_text.push_back(textline);
	}
}

void TextQuery::build_map()
{
	for(line_no line_num = 0; line_num != lines_of_text.size(); ++line_num)
	{
		istringstream line(lines_of_text[line_num]);
		string word;
		while (line >> word)
		{
			word_map[word].insert(line_num);
			//word_map.insert(make_pair(word, line_num));
			//word_map.insert(map<std::string, line_no>::value_type(word, line_no));
		}
	}
}

std::set<TextQuery::line_no>
TextQuery::run_query(const string &query_word) const
{
	map<string, set<line_no> >::const_iterator loc = word_map.find(query_word);
	if (loc == word_map.end())
		return set<line_no>(); //not found, return empty set
	else 
		return loc->second;
}

std::string TextQuery::text_line(line_no line) const
{
	if (line < lines_of_text.size())
		return lines_of_text[line];
	else
		throw std::out_of_range("line number out of range");
}

ifstream& open_file(ifstream &in, const string &file)
{
	in.close(); // close in case it was already open
	in.clear(); // clear any existing errors
	// if the open fails, the stream will be in an invalid state
	in.open(file.c_str()); // open the file we were given
	return in; // condition state is good if open succeeded
}

string make_plural(size_t ctr, const string &word,
				   const string &ending)
{
	return (ctr == 1) ? word : word + ending;
}

void printf_resluts(const set<TextQuery::line_no> &locs, const std::string &sought, const TextQuery &file)
{
	typedef set<TextQuery::line_no> line_nums;
	line_nums::size_type size = locs.size();
	cout << "\n" << sought << "occurs "
		 << size << make_plural(size, "time", "s")
		 << endl;
	line_nums::const_iterator it = locs.begin();
	for (; it != locs.end(); it++)
	{
		cout << "\t(line"
			 << (*it) + 1 << ")"
			 << file.text_line(*it)
			 << endl;
	}
}

int main(int argc, char **argv)
{
	ifstream infile("C:\\1.txt");
	/*if (argc < 2 || !open_file(infile, argv[1]))
	{
		cerr << "No input file" << endl;
		return EXIT_FAILURE;
	}*/
	
	TextQuery tq;
	tq.read_file(infile);

	while (true)
	{
		cout << "Enter word to look for, or q to quit: ";
		string s;
		cin >> s;
		if (!cin || s == "q")
			break;
		set<TextQuery::line_no> locs = tq.run_query(s);
		printf_resluts(locs, s, tq);
	}
	return 0;
}

注意上面例子中:

word_map[word].insert(line_num);
不能替换成如下两种形式
//word_map.insert(make_pair(word, line_num));
//word_map.insert(map<std::string, line_no>::value_type(word, line_no));

因为make_pair的两个实参必须是具体的值,而不能是变量。

参考:

[1] http://blog.163.com/zhoumhan_0351/blog/static/399542272010227112325224/

http://blog.163.com/zhoumhan_0351/blog/static/39954227201032392545410/

http://blog.163.com/zhoumhan_0351/blog/static/399542272010229828061/

http://blog.163.com/zhoumhan_0351/blog/static/39954227201038102838349/

http://blog.163.com/zhoumhan_0351/blog/static/399542272010396030501/

http://blog.163.com/zhoumhan_0351/blog/static/39954227201039112031737/

http://blog.163.com/zhoumhan_0351/blog/static/39954227201022994439573/

posted @ 2011-03-20 19:44  浪里飞  阅读(686)  评论(0编辑  收藏  举报