重学C++Primer笔记10---容器常用用法总结与归纳
2015-10-14 12:40
375 查看
0 迭代器
注意点:迭代器的操作是有限的:均可自增、自减、==、!=、解引用、读取对象成员(.);
对于顺序容器vector支持迭代器加减一个整数,其他的常用容器不支持;
测试程序:
#include <iostream> #include <string> #include <vector> #include <list> #include <queue> #include <map> #include <set> using namespace std; int main(int argc,char *argv[]) { vector<string> svec; list<string> slist; deque<string> sdeque; map<string, int> smap; set<string> sset; //vector在内存是连续存储的,类似数组,可以通过加上一个整数来移动下标 vector<string>::iterator svec_it = svec.begin() + svec.size()/2; //list<string>::iterator slist_it = svec.begin() + svec.size()/2; //error:list不支持加减一个整数 //deque<string>::iterator sdeque_it = svec.begin() + svec.size()/2; //error:deque不支持加减一个整数 //map<string, int>::iterator smap_it = svec.begin() + svec.size()/2; //error:map不支持加减一个整数 //set<string>::iterator sset_it = svec.begin() + svec.size()/2; //error:set不支持加减一个整数 return 0; }
1 顺序容器
注意点:指定元素个数的容器初始化只适用于顺序容器。如形式为C c(n,t)或C c(n)这两种形式的初始化。
直接将一个容器复制给另一个容器时,类型必须匹配:容器类型和元素类型都必须相同,如vector ivec2(ivec1);。
使用迭代器时,不要求容器类型相同,容器内的元素类型也可以不相同,只要相互兼容,能够将要复制的元素转换为所构建的形容器的元素类型,即可实现复制,如list slist(svec.begin(),svec.end());。
指针就是迭代器,允许通过使用内置数组中的一对指针初始化容器:
char *color[] = {“black”,”red”,”yellow”,”blue”};
size_t color_size = sizeof(color)/sizeof(char *);
list color1(color,color + color_size);
除了引用类型,所有内置或复合类型都可以做元素类型。
除IO标准库类型之外,所有其他标准库类型都是有效的容器元素类型,容器本身也是。
容器的容器注意尖括号: vector< vector > lines;隔开,不然会导致编译时错误。
list容器的迭代器既不支持算术运算(加法或减法),也不支持关系运算(<=,<,>=,>),只提供前置和后置的自增和自减运算以及相等和不等运算。
使用无效的迭代器会导致严重的运行时错误,如erase函数删除了元素,指向该元素的迭代器就无效了。
所有的顺序容器都支持push_back操作,在容器尾部插入一个元素的功能。而push_font只适用于list和deque容器类型。
不要存储end操作返回的迭代器,添加或删除deque或vector容器内的元素都会导致存储的迭代器失效。while(fisrt != v.end()){…}才好。
所有的容器都提供四种与容器大小相关的操作:size(),max_size(),empty(),resize(n),resize(n,t),包括关联容器。
c.back()、c.front()分别返回容器c的最后一个元素的引用,如果c为空,则该操作未定义。相当于对begin()、end()-1进行解引用。
pop_front()和pop_back()函数用于删除容器内的第一个和最后一个元素,当vector容器不支持pop_front操作,删除指定元素返回void。当然还有c.erase(p),c.erase(b,e)函数。
vector:
最常用的容器类型,支持对元素的快速随机访问,可以高效的在容器尾部添加和删除元素,但是在其他任何位置上的插入或删除运算则需要付出昂贵的代价。
list:
只支持元素的顺序访问,但是在list内部任何位置的插入和删除都非常迅速。
deque:
支持在首尾部快速的删除和插入元素
string:
字符串类型,一般的,可视为字符容器,支持大多数容器操作,与vector有大多数相同操作,但不支持栈方式操纵容器,即不能在string类型中使用font、back和pop_back操作。
s.substr(pos,n),返回一个下标从pos开始的n个字符的string。
s.substr(pos),返回一个下标从pos开始到s末尾的所有字符的string。
s.replace(pos,len,args),删除s中从下标pos开始的len个字符,用args指定的字符替换,返回s的引用。
s.replace(b,e,args),删除迭代器b和e标记范围内的所有字符,用args代替,返回s的引用。
s.find(args),在s中查找args第一次出现的pos,没有则返回string::npos
s.rfind(args),在s中查找args最后一次出现的pos
s.find_first_of(args)
s.find_first_of(string),查找任意字符,s中是否有string中的字符。
s.find_first_of(string,pos);
s.find_last_of(args)
s.find_first_not_of(args)
s.find_last_not_of(args)
2 关联容器
注意点:关联容器不提供front、push_front、pop_front、back、push_back及pop_back操作。
map是pair类型(对组类型)的集合,键+值
在使用迭代器遍历map容器时,迭代器指向的元素按键的升序排列。
map的键值不能修改,为const修饰,只能修改值成员。
对map迭代器进行解引用将产生pair类型的对象,即可以使用first或second获取内容。
使用下标访问map与使用下标访问数组或vector的行为截然不同:用下标访问不存在的元素将导致在map容器中添加一个新的元素,它的键即为该下标。使用insert代替下标运算,可以避免这个不必要的初始化。使用insert插入元素时,如果键已经存在容器中,则insert不做任何操作,即不做值替换。
set不支持下标操作符,键值唯一,不能修改。
multimap中,同一个键可以关联多个值,且同一个键所关联的元素必然相邻存放。因此只要找到首端迭代器,就可以遍历同一键所关联的所有的值。
使用关联容器需包含对应的头文件,如
#include<map>、
#include<set>
map
m.count(k),返回m中k出现的次数,适用于multimap和map,很明显,在map中,如果k存在,则返回值肯定为1。
m.find(k),在m中按k索引,存在,则返回指向该元素的迭代器。不存在,则返回超出末端迭代器。
m.erase(k),
m.erase(p),
m.erase(b,e),
m.insert(e),e是一个用在m上的value_type类型的值。
m.insert(b,e)
m.insert(iter,e)
set
insert
count
find
erase
multimap
multiset
3 应用:文本查询
#include <iostream> #include <fstream> #include <vector> #include <map> #include <set> #include <cstdlib> #include <stdexcept> #include <sstream> using namespace std; class TextQuery{ public: typedef vector<string>::size_type line_no; void read_file(ifstream &is); set<line_no> run_query(const string&) const; string text_line(line_no) const; private: ifstream& open_file(ifstream &,const string &); void store_file(ifstream&); void build_map(); vector<string> lines_of_text; map< string, set<line_no> > word_map; }; void TextQuery::read_file(ifstream &is) { store_file(is); build_map(); } string TextQuery::text_line(line_no line) const { if(line < lines_of_text.size()) return lines_of_text[line]; //out_of_range,c++异常类, throw out_of_range("line number out of range"); } 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()) //返回空set对象 return set<line_no>(); else return loc->second; } ifstream& TextQuery::open_file(ifstream &in,const string &file) { in.close(); in.clear(); in.open(file.c_str()); return in; } //----------------------------------------------------------- //将文件中的每一行字符串作为一个元素依次存放到vector中 //----------------------------------------------------------- void TextQuery::store_file(ifstream&is) { string textline; while(getline(is,textline)) lines_of_text.push_back(textline); } //----------------------------------------------------------- //将存放每一行字符串的vector的元素依次取出,将其分解为单词,并将单词的行数保存到map< string, set<line_no> >中 //----------------------------------------------------------- void TextQuery::build_map() { for(line_no line_num = 0; line_num != lines_of_text.size(); ++line_num){ //绑定行字符串到istringstream istringstream line(lines_of_text[line_num]); string word; //循环从行字符串读取单词到string类型word while(line >> word){ //将行号插入到键值为word,值为vector类型的map中 word_map[word].insert(line_num); } } } string make_plural(size_t ctr, const string &word, const string &ending) { return (ctr == 1) ? word : word + ending; } void print_results(const set<TextQuery::line_no>& locs, const 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; 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); print_results(locs,s,tq); } return EXIT_SUCCESS; }
相关文章推荐
- C++Primer笔记之关联容器的使用详解
- C++Primer笔记之顺序容器的使用详解
- map容器,下标行为的编程意义
- 【C++基础】 顺序容器
- STL中map的基本操作
- C++ Primer学习之(10)——关联容器
- C++顺序容器
- C++关联容器
- 重学C++Primer笔记7---标准IO库中输入输出流控制
- C++---if(!cin)与if(!(cin >> xxx))
- 初探STL之关联容器
- C++ Primer中文本查询示例Query的实现
- 标准库+类——实现文本查询
- c++primer之顺序容器(容器库概览)
- c++primer之顺序容器(访问元素)
- C++ Primer(4th)文本查询自编代码
- c++ 关联容器详解——从内部结构到应用
- C++ Primer 学习笔记_28_STL实践与分析(2) --顺序容器的操作(上)
- C++ Primer 学习笔记_29_STL实践与分析(3) --顺序容器的操作(下)
- C++ primer笔记——第九章 顺序容器