先总结本章所学的知识。
第三章总结
- 一开始学习了指针算术运算,知道了指针可以用下标运算符(如array[2])来取出其指向的元素,或者*(array+2)来取出其指向的元素,array++,*array++,都是指针的算术运算。
- 然后就是了解泛型指针,泛型指针的定义是针对于容器的,必须是容器的定义格式::iterator
指针名,如vector<string>:;iterator iter=svec.begin();
泛型指针和普通指针在算术操作上一样,如果想通过泛型指针知道容器的大小,用**泛型指针->size()**即可,然后还可以运用在函数模板之中。
比如
template<typename IteratorType,......>
IteratorType find(IteratorType first,......)
....
-
然后了解了一些泛型算法,以及所有容器(包括)的共同操作,!=,==,赋值运算符=,empty(),size(),clear(),begin(),end(),insert(),erase()等,具体可查书或搜索引擎。
-
然后是使用顺序性容器,比如list,deque,这些容器增删效率比vector高。符合容器共同操作,使用时包含对应的头文件比如
#include<list>,#lnclude<deque>
等。
注意可以产生空容器,就像这样vector<int>ivec,list<string>slist,deque<int>line
等
各种插入删除操作,push_back(),pop_back(),适用于vector,list,deque容器,push_front(),pop_front()等,不适用于vector容器但适用于list,deque容器,读取首个元素的值用容器.front()。末尾元素的值用容器.back()
容器复制:把slist复制给slist2list<string>slist2(slist);
-
然后使用泛型算法,在使用泛型算法前包含头文件
#include<algorithm>
介绍了很多泛型算法,具体查搜索引擎或书 -
然后介绍了如何设计一个泛型算法,这节难度很大,读了三遍。学习了函数对象(function object),有六个算术运算,六个关系运算,三个逻辑运算,举例:
plus<type>,divides<type>(除法),less_equal<type>,logical_and<type>
学习了函数对象适配器(function object adapter),其中有bind1st/2nd用来把指定的数值绑定在函数对象的第一个参数或第二个参数上。然后让第二个参数或第一个参数和该绑定的指定数值进行比较,极大提高了效率,及便利。用函数对象前要包含头文件#include<functional>
negator对函数对象的真伪值取反,如not1(bind2nd(less<int>,10))))
,那就是找出大于等于10的元素出来(容器里每个元素和指定的值10进行比较,大于等于10的元素摘出来) -
然后是使用map和set,map可以查询某文本中某字眼(或元素、结点等)出现的次数,set用来存储某字眼(或元素、结点等),防止下次遍历再遍历到他,或者你用set可以记录排除的字眼。注意使用前包含头文件
#include<map>和#include<set>,你用哪个就包含哪个,都用都包含。
还介绍了map三个查询法和set的插入,单一参数的insert(),双参数的insert,泛型指针set型,及和set相关的泛型算法,具体查一下我写的那一节的笔记 -
然后是如何使用iterator inserter,可以用于动态容器中,消除了得为目标容器(比如复制操作,肯定得需要目标容器)考虑其大小的问题。介绍了back_inserter(),inserter(),front_inserter(),用之前要包含头文件
#include<iterator>
,具体用法查那一节笔记。 -
最后讲了如何使用iostream iterator,用之前也要包含头文件
#include<iterator>
,标准库定义了供输入输出的iostream iterator类,称为istream_iterator和ostream_iterator,具体用法查那一节笔记。这些泛型指针多和泛型算法copy()配合使用,会让输入输出至标准输入/输出设备(屏幕、文件等)的代码更加简洁,可读性变强。
插播一个注意事项:事实证明不在模板函数里定义的泛型指针不用在开头加typename
好了,接下来手撕习题,看看能得到什么,避免踩什么坑。
习题
详细分析过程都在注释里,看注释就能明白,这里除非我不贴代码,我都不解释的。
3-1
/** 模块化、结构化拆解问题,分析问题,解决问题。
* 读取的文件数据:This is a shabi,I am your father and you are my son.
*/
#include<iostream>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<fstream>
using namespace std;
int main()
{
ifstream in_file("word.txt");//要求0,读取文本文件
if(!in_file)
{
cerr<<"Cannot read the word.txt!\n";
return -1;
}
set<string>word_exclusion;
string exclusionWordArray[6]={
"a","an","or","the","and","but"};
vector<string>exclusionWordVec(exclusionWordArray,exclusionWordArray+6);
word_exclusion.insert(exclusionWordVec.begin(),exclusionWordVec.end());//要求2--定义一份由排除字眼组成的set,其中包含上述的单字
map<string,int>words;
string word;
while(in_file>>word)
{
if(word_exclusion.count(word))
{
continue;//要求3--将某单子放入map之前,先确定该单字并不在“排除字集”中。
}
words[word]++;//要求1--将文件中的每个单子存入map(已被set筛选过)
}
map<string,int>::iterator mapiter=words.begin();//注意格式。
for(;mapiter!=words.end();mapiter++)
{
cout<<"key:"<<mapiter->first<<endl;
cout<<"value:"<<mapiter->second<<endl;
}//要求4--文本文件读取完毕,显示一份单字清单,并显示各单字的出现次数
return 0;
/** 发现:1.统计字眼(这里是单字)的时候,以空格为界限!!比如shabi,I、son.就统计为一个字眼了
*
*/
}
运行结果:
读取的文件里的内容:
显示在屏幕的内容
答案源码分析:
#include<iostream>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<fstream>
using namespace std;
void initialize_exclusion_set(set<string>&);
void process_file(map<string,int>&,const set<string>&,ifstream&);
void user_query(const map<string,int>&);
void display_word_count(const map<string,int>&,ofstream&);
//学习一下人家的函数声明,map,set是可以作为参数(形参的),然后避免多开内存和修改,有目的的用了const和引用&
int main()
{
ifstream ifile("column.txt");
ofstream ofile("column.map");//读取一个文件里的内容ÿ