首页 > 代码库 > C++primer笔记:IO库、顺序容器、关联容器、面向对象、泛型算法、模板和泛型编程
C++primer笔记:IO库、顺序容器、关联容器、面向对象、泛型算法、模板和泛型编程
第八章:IO库
不直接来处理输入输出,而是通过在标准库中的一些类型来处理io istream ostream cin cout cerr getline函数 iostream:定义了用于基本读写流的基本类型 fstream: 定义了基本的读写命名文件的类型 sstream:定义了读写内存的string对象的类型 IO对象无拷贝或者赋值 条件状态:IO定义了一些函数和标志,可以帮助我们访问和操作流得条件状态 strm::iostate 条件状态的完整功能 strm::badbit 流已崩溃 strm::failbit io操作已经失败 strm:eofbit 流到达了文件的结束 strm:goodbit 指出流未处于错误状态 管理条件状态: 管理输出缓冲: —————————————————————————————————————————————————————————————————————————————————————————————————————————————————— 文件输入输出: 头文件的fstream: ifstream:给定文件读取数据, ofstream: 给定文件写入数据, fstream: 读写给定文件 fstream fstrm; fstream fstrm; fstream.open(); fstream.close(); fstream.is_close(); 文件模式: 每个流对应的一个关联模式:文件模式 in 读方式打开 out 写方式打开 app 每次写操作前均定位到文件末尾 ate 打开文件后就立即定位到文件末尾 trunc 截断文件 binary 二进制文件 —————————————————————————————————————————————————————————————————————————————————————————————————————————————————— string流 sstream头文件定义了三个类型来支持内存IO istringstream: 从string读取数据 ostringstream: 向string写入数据 stringstream :既可以从string也可以向string写数据 sstream中定义的类型继承来至于我们使用的iostream头文件的流的类型 还增加了与string流相关类型的 关系: iostream | sstream | istringstream、ostringstream 总结: C++使用标准库类来处理面向流的输入输出 iostream:处理控制台IO fstream: 处理命名文件IO stringstream:完成内存的string的IO 条件状态:可以被任何流类使用的一组函数和标志,用来指出给定流是否可用 文件模式:类fstream定义的一组标志,在打开文件的时候,控制文件如何被使用 -iostream -sstream -stringstream、istringstream、ostringstream -fstream、ifstream、ofstream __________________________________________________________________________________________________________________ 第九章:容器 9.1顺序容器: vector:可变大小数组,快速随机访问,在尾部之外的位置插入或者删除元素都很慢,尾部插入删除速度快 array: 固定大小数组,快速随机访问 string:与vector相似,但专门用于保存字符,字符串数组,随机访问快,尾部插入删除速度快, list:双向链表,只支持双向顺序访问,任何位置插入删除都很快 forward_list:单向链表,只支持单向顺序访问,任何位置插入删除都很快 deque:双端队列,支持快速随机访问,在头尾插入删除很快, 9.2容器操作: 类型别名: iterator:此容器的迭代器 const_iterator: size_type: 容器的大小,这个大小指的是在特定类型下的大小 value_type:元素值对应的类型 difference_type:两个不同迭代器之间的距离 赋值和swap: swap(a,b) a.swap(b) C1={a,b,c...} 大小: c.size() c.max_size() c.empty() 添加删除元素: c.insert() c.clear() c.erase() 获取迭代器 c.begin(),c.end() c.cbenin(),c.cend() 反向容器: reverse_iterator:按逆序寻址元素的迭代器 c.rbegin(),c.rend(): c.crbegin(),c.crend(): 迭代器范围:由一对迭代器表示,两个迭代器分别指向同一个容器中的元素 分别被称为begin和end,他们标记了容器元素的一个范围 第二个迭代器指向尾元素之后的位置,[begin,end),但不包含最后一个元素,也不能指向begin之前的元素 [begin,end) 使用左闭合的编程假定:while(begin!=end) c.begin() c.rbegin() //reverse c.cbegin() //const c.crbegin() //const_reverse 注:以C开头的版本都是C++新引入的,不以C开头的都是被重载过的 assign() (1) list<string> names; vector<const char*> old; names.assign(old.cbegin(),old.cend()); (2) list1.assign(10,"table"); array 与内置的数组不同,标准库array允许赋值,赋值左右两边的运算对象具有相同的类型 array<int,10> a1={1,2,3,4,5,6,7,8,9,0}; array<int,10> a2={0}; array不支持assign,不允许用花括号包围的值列表进行赋值 swap 使用swap:交换两个相同的类型容器的内容 调用swap之后,两个容器中的元素将会交换,除array之外,交换两个容器内容的操作保证会很快, 元素本身未交换,swap只是交换了两个容器内部的数据结构 但是对于array,会真正交换两个元素 元素不会被移动。意味着除string外,指向容器的迭代器,引用,指针在swap操作之后不会失效 他们仍然指向swap操作之前的哪些元素,但是swwap之后,这些元素已经属于不同的元素了 但是对一个string的调用会导致swap之后的迭代器和引用,指针会失效 9.3 顺序容器操作 添加元素: c.push_back(t) 尾部创建 c.push_front(t) 头部创建 push_back(): 将元素追加到vector的尾部 push_front():将元素追加到vector的头部 insert(): 将元素追加到vector的任意位置 emplace_back:直接在内存中创建元素 push_back: 在容器的局部创建元素 访问元素: c.at(n) c.back() c.front() c[n] 删除元素: c.pop_back() c.pop_front() c.erase(ele1,ele2) c.clear() 改变容器的大小:resize() 容器操作可能使迭代器失效: (1):如果是vector或者string,若存储空间重新分配,则指向迭代器或者指针,引用会失效 若存储空间未重新分配,则插入之前的会不变,之后的失效 (2):deque:插入到首尾之外的会失效,在首尾添加会使迭代器失效,但引用和指针不变 (3):list和for_ward:指向容器的迭代器(尾后和首前)和指针、引用仍有效 额外的string操作 1:构造string的其他方法: string(s1,pos,len); s.substr(0,5); 2:改变string的其他方法: assign、insert、erase append、replace函数 3:string的搜索操作 s.find(args); 搜索出现的第一次的位置 s.rfind(args); 搜索出现的最后一次的位置 s.find_first_of(args); 搜索任何一个字符出现的第一次的位置 s.find_last_of(args); 搜索任何一个字符出现的最后一次的位置 s.find_first_not_of(args);搜索任何一个字符不出现的第一次的位置 s.find_last_not_of(args); 搜索任何一个字符不出现的最后一次的位置 4 compare函数 compare函数与C语言函数的strcmp函数类似, s.compare返回0,正数,负数 5 数值转换函数: to_string(val); 转换成string stod(s); 转换成double stof(s); 转换成float stoi(s); 转换成int stol(s); 转换成long stoul(s); 转换成unsigned long stoull(s); 转换成unsigned long long 容器适配器:stack、queue、priority_queue 除了顺序容器之外:还定义了3个顺序适配器:stack、queue、priority_queue 一个适配器是一种机制,能使某种事物看起来像另外一些事物, 一个适配器接受一种已有的容器,使其行为看起来像另外一种事物 stack、queue、priority_queue 支持的操作: size_type: value_type: empty(); swap(); 定义1个适配器: deque<int> deq; stack<int> stk(deq); stack<string,vector<string>> str_stk; //在vector上的实现的栈, 两个类型函数;默认情况下:stack和queue是基于deque实现的 priority_queue是在vector上实现的 stack:满足push_back、pop_back、back 可以基于除array和forward_list之外的上面 queue:满足push_back、back、front和push_front 可以基于list和deque之上,不能vector priority_queue:随机访问,push_back、front 可以基于vector和deque之上,不能list ————————————————————————————————————————————————————————————————————————————————————————————————————————————————— 第10章:泛型算法 10.1泛型算法:独立于容器的通用算法 在头文件algorithm里面 不直接作用于容器,而是遍历两个迭代器之间的一个元素范围 find(vec.cbegin,vec.end,val) 泛型算法永远不会执行容器的操作,他们只会独立于迭代器上面 迭代器令算法不依赖于容器,但算法依赖于元素类型的操作 10.2 初识泛型算法 只读算法: 搜索find 求和连接accumulate 判断相同equal,只有3个迭代器, 写容器元素的算法:填充赋值fill: 2个迭代器,3个参数 拷贝copy:2个迭代器,3个参数 replace():2个迭代器,4个参数 replace_copy():3个迭代器,5个参数 重排:sort unique:只有2个迭代器 10.3迭代器 插入迭代器:back_insert/front_insert/insert 流迭代器 : istream_iterator/ostream_iterator 反向迭代器: rbegin/rend/crbegin/crend 移动迭代器: 10.5泛型算法结构 5个迭代器类别 输入:只读不写,单遍扫描,只能递增 输出:只写不读,单遍扫描,只能递增 前向:读写均可,多遍扫描,只能递增 replace 双向:读写均可,多遍扫描,能递增递减 reverse 随机访问:可读写,多遍扫描, sort _______________________________________________________________________________________________________________ 第11章:关联容器 按照关键字来保存和访问的 map和set等 按关键字的有序保存元素: map 关联数组,保存关键字-值对 set 关键字即可 multimap 关键字可重复 multiset 关键字可重复 按关键字的无序集合: unordered_map 哈希组织的map unordered_set 哈希组织的set unordered_multimap 哈希组织的map,关键字可重复 unordered_multiset 哈希组织的set,关键字可重复 使用map: map<string,size_t> word_count; //建立map的键值对类型:string-size_t string word; //建立健:word while(cin>>word) ++word_count[word]; for(const auto&w:word_count) cout<<w.first<<"oocures"<<w.second<<endl; 使用set: set<string> exclude={"the","but","he","good","wo","hi"}; while(cin>>word) if(exclude.fide(word)==exclude.end()) ++word_count[word]; 关联容器不支持:push_front和push_back 定义容器: map<string,string> authors={{"he","jim"}, {"she","tom"}, {"it","lili"}}; pair类型:定义在头文件:utility里面 保存两个数据成员,类似容器,pair用来生成特定类型的模板 pair操作 pair<T1,T2> p(v1,v2); make_pair(v1,v2); p.first; p.second; p1==p2; p1!=p2; 关联容器的额外的类型别名 key_type; mapped_type; //只适用于map,每个关键字关联的类型, value_type; //对于set,与key_type一致 //对于map;为pair<const key_type,mapped_type> 只有map类型定义了mapped_type 例如: map<string,int>::mapped_type v1; //v1 int map<string,int>::key_type v2; //v2 string map<string,int>::value_type v3; //v3 pair<const string,int> 关联容器的迭代器:会获得value_type类型的引用 对于map而言,value_type是一个pair类型,first成员保存const关键字,second保存值 对于set迭代器,是const的,只允许访问set不能改变关键字 map<string,size_t> word_count; //map关联容器 auto map_it=word_count.begin(); //map迭代器 cout<<map_it->first; //迭代器指向关键字 cout<<map_it->second; //迭代器指向值 遍历关联容器:map和set支持begin和end操作 auto map_it=word_count.cbegin() while(map_it!=word_count.cend()) { cout<<map_it->first; //打印键 cout<<map_it->second; //打印值 ++map_it; } 添加元素:insert:有两个版本,分别接受一对迭代器或者一个初始化列表 map的insert操作的元素类型必须是pair c.insert(ivec.begin(),ivec.end()); //set的insert c.insert({1,2,3,4,5}); //set的insert word_count.insert({word,1}); //map的insert类型 word_count.insert(make_pair(word,1)); //map的insert类型 word_count.insert(map<string,size_type>::value_type(word,1));//map的insert类型 删除元素:erase 下标操作:下标运算符和at函数,但是set,multimap,unorder_multimap不支持下标 c[k]和c.at(k) 访问元素:find、count 无序容器:新的标准里面新增加了4个新的无序容器 无序容器使用一个哈希函数将元素映射到桶 为了得到元素,先要计算元素的哈希值,他指出应该搜索那个桶 容器将具有一个特定的哈希值的所有元素都保存在相同的桶里面 桶接口: c.bucket_count() 正在使用桶的数目 c.max_bucket_count() 容器里面的最大容纳的通的数目 c.bucket_size(n) 第n个桶有多少个元素 c.bucket(k) 关键字的k在哪个桶里面 桶迭代: local_iterator const_local_iterator c.begin(n),c.end(n) c.cbegin(n),c.cend(n) 哈希策略: c.looad_factor() : 每个桶的平均元素数量,返回float值 c.max_load_factor() :c试图维护每个桶的平均元素数量,必要的时候添加新的桶 c.rehash(n) :重组hash,使得max_bucket_count>=n c.reserve(n) :重组hash,使得c可以保存n个元素,而且不用rehash 无序容器对于关键字的类型要求: 默认情况下使用==运算符来比较元素 而且使用一个hash<key_type>类型的对象来生成每个元素的哈希值 对应的是默认的hash模板 总结: hash:标准的库模板,无序容器用它来管理元素的位置 关联容器:保存对象的集合,支持通过关键字的高效查找 关联数组:元素通过关键字而不是位置来索引的数组 key_type: 就是关联容器的关键字的类型 mapped_type:就是映射中关键字的关键字关联的值的类型 value_type:容器里面的元素的类型,对于map容器是一个pair,first是const_key_type,second是mapped_type pair:保存名为first和second的数据成员,是一个模板类型,接受两个类型参数,作为其两个对应的成员的类型 ______________________________________________________________________________________________________________ 第12章:动态内存 ______________________________________________________________________________________________________________ 第15章:面向对象程序设计 15.3虚函数:每个虚函数都必须定义 对于虚函数的调用可能直到运行时才被解析 virtual虚函数关键字 final和override说明符 C++11里面使用override来说明派生类里面的虚函数 struct B{ virtual void f1(int) const; vittual void f2(); } struct D:B{ void f1(int) const override; } _________________________________________________________________________________________________________________ 第16章:模板和泛型编程 泛型编程:独立于任何特定的类型来编写代码 泛型编程:容器、迭代器、算法 只是对于类型不同 16.1定义模板 定义模板:只是参数对应的类型不同 1:函数模板 template <typename T> int compare(const T &v1,const T &v2) { if(v1<v2) return -1; if(v1<v2) return 1; return 0; } 关键字:template 后跟模型参数列表 用<>表示 编译器用推断的模板参数来为我们实例化一个特定版本的参数 模板类型参数:template后面必须跟上typename或者class template <typename T,class U> T clac(const T&,const T &) 非类型参数:表示的是一个值而非类型,但必须是常量表达式, template <unsigned N,unsigned M> int compare(const char(&p1)[N],const char(&p2)[M]) { return strcmp(p1,p2); } inline和constexpr的函数模板 template <typename T> inline T min(const T&,const T&) inline放在模板参数列表后,返回类型之前 模板编译:当编译器遇到一个模板定义的时候,并不生成代码 只有实例化一个特定模板时候,才会生成特定的代码 只有使用而不是被定义模板的时候才会生成代码 模板的头文件通常既会包含声明,也会包含定义 类模板:编译器不能推断麻痹你参数类型,必须通过额外的信息 template <typename T> class Bob{}; 可变参数模板:参数包 模板参数包 函数参数包
C++primer笔记:IO库、顺序容器、关联容器、面向对象、泛型算法、模板和泛型编程
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。