12、C++Primer 4 thノート、関連容器(2)

6068 ワード

1、map、setコンテナでは、1つのキーが1つのインスタンスにしか対応しません.Multimapおよびmultisetタイプでは、1つのキーが複数のインスタンスに対応できるようにします.サポートされる操作はmapとsetの操作と同じで、例外は1つだけで、multimapは下付き演算をサポートしません.setとmultisetはストレージキーに特化しています.
2、関連コンテナmapとsetの要素は順番に格納される.multimapとmultsetも同じです.したがって、multimapおよびmultisetコンテナでは、キーが複数のインスタンスに対応する場合、これらのインスタンスはコンテナに隣接して格納されます.multimapまたはmultisetコンテナを反復すると、特定のキーに関連付けられたすべての要素が順次返されることが保証されます.
3、multimapとmultisetで要素を探す場合、一般的に以下の3つの方法があります.
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 << "
" << 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の2つの実パラメータは、変数ではなく特定の値でなければなりません.
参照先:
[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/