1.指针的运算
- 可以对指针使用下标运算符
下标运算符就相当于在起始地址的基础上加上索引值,产生某个元素的地址
#include<iostream>
using namespace std;
int main(){
int a[]={1,2,3,4,5};
int *p=a;
cout << p[1];//或者cout << *(p+1); cout<< *p[1]是错误的
}
上面程序的输出为2,
所以
p[1] = *(p+1)
对于书中的对vector和array的泛型算法:
template <typename elemtype>
elemtype* find(const elemtype *array,int size,const elemtype &value){ // array就是数组的首地址
if(!array || size<1){
return 0;
}
for(int i=0;i<size;i++){
if(array[i]==value)
return &array[i]; //可以看出array[i]是一个具体的值。而不是对象,就相当于数组一样
}
return 0;
}
除了使用指针的下标计算外,还可以:
template <typename elemtype>
elemtype* find(const elemtype *array,int size,const elemtype &value){
if(!array || size<1){
return 0;
}
for(int i=0;i<size;i++,++array){ //由此 for语句不仅仅是每个部分一句,可以多句
if(*array==value) //由地址提领到他的值
return array; //返回当前地址
}
return 0;
}
2.iterator
需要实现的功能
for(iter=vec.begin();iter !=vec.end();++iter){
cout << *iter << endl;
}
vector<int> vec;
vector<int> ::iterator iter=vec.begin()
可以通过iter调用vector的函数
iter->size()
3.容器公用的操作
4.使用顺序性容器
定义容器的方式
// 产生空的容器
vector<int> vec;
list<string> ilist;
//产生特定大小的容器,每个元素为默认值,int double默认值为0
list<int> ilist(1024);
vector<string> ivec(32);
//产生特定大小的容器,并为每个元素赋初值
vector<int> ivec(10,-1)
list<string> slist(16,"abcdefg")
//通过对iterator产生容器
int ia[8]={1,2,3,4,5,6,7,8}
vector<int> fib(ia,ia+8)
//通过一个容器,产生另外一个容器
list<string> slist;
list<string> slist2(slist)
容器的插入和删除的操作
push_back()//末尾插入
pop_back()//末尾删除
5.使用泛型算法
6.设计泛型算法
- 设计一个程序,给与一个vector,现在返回一个vector,内含原vector中所有小于10的元素
vector<int>less_than_10(const vector<int> &vec){
vector<int> nvec;
for (int i = 0; i < vec.size(); ++i) {
if(vec[i]<10)
nvec.push_back(vec[i]);
}
return nvec;
}
- 现在要去改进程序,可以指定边界数,同时可以指定大于、小于、等于
vector<int> filter(const vector<int> &vec,int value,bool (*pred)(int,int)){
vector<int> nvec;
for(int i=0;i<vec.size();i++){
if(pred(vec[i],value))
nvec.push_back(vec[i]);
}
return nvec;
}
bool less_than(int a,int b){
return a<b ? true:false;
}
bool more_than(int a,int b){
return a>b ? true:false;
}
这里使用函数指针,通过函数指针可以达到指定大于小于的作用,记住,函数名和数组名一样,本质上就是指针,是一个地址。
- 实际的完整程序
#include <iostream>
#include <vector>
using namespace std;
vector<int>less_than_10(const vector<int> &vec){
vector<int> nvec;
for (int i = 0; i < vec.size(); ++i) {
if(vec[i]<10)
nvec.push_back(vec[i]);
}
return nvec;
}
//使用函数指针
vector<int> filter(const vector<int> &vec,int value,bool (*pred)(int,int)){
vector<int> nvec;
for(int i=0;i<vec.size();i++){
if(pred(vec[i],value))
nvec.push_back(vec[i]);
}
return nvec;
}
bool less_than(int a,int b){
return a<b ? true:false;
}
bool more_than(int a,int b){
return a>b ? true:false;
}
//vector<int> avec=filter(big_vec,value,less_than)
int main(){
int a[6];
for(int i=0;i<6;i++){
int b;
cin >> b;
a[i]=b;
}
vector<int>vec(a,a+6);
vector<int> svec=filter(vec,5,less_than);
for(int i=0;i<svec.size();i++){
cout << svec[i] << endl;
}
}
- function object
//头文件
#include<functional>
可以实现:
sort(vec.begin(),vec.end(),greater<int>)
通过greater,可以使得排列之后的容器是从大到小
常用的有:
算术运算符:plus<type>、minus<type>、negate<type>、multiplies<type>、divides<type>
关系运算符:less<type>、less_equal<type>、greater<type>、greater_equal<type>、
equal<type>、not_equal_to<type>
逻辑运算符:logical_and<type>、logical_or<type>、logical_not<type>
- function object adapter
例如上面的less<type>,是希望外界传入两个值,如果符合要求,就返回true,而我们设置的filter函数事希望传入的一个值一直和设定的值比较,所以需要使用adapter,将less<type>转化为一元运算符。
使用bind1st将值绑定到第一操作数,bind2nd将值绑定到第二操作数。
vector<int> filter(const vector<int> &vec,int value,less<int> <){
vector<int> nvec;
vector<int> ::iterator iter=nvec.begin();
while((iter=find_if(iter,nvec.end(),bind2nd(lt,value)))!=nvec.end()){
nvec.push_back(*iter);
iter++;
}
return nvec;
}
7.map
map为一对数值,包含key和value
map<string,int> words
words["vermeer"]=1;
string tword;
while(cin >> tword)
words[tword]++;
- 注意一下要点
int count=0;
if(!(count=words["vermeer"]))
这种做法,当words中并不包含vermeer这个键的时候,会自动的加入到words中,同时value会被置为默认值。
- map.find()
words.find("vermeer")
返回一个iterator,指向当前的pair,如果不存在,则返回end()
- map.count()
words.count["vermeer']
返回数量
注意:vector中没有count和find这个类函数,就是不能使用vector.count()的方式,但是可以用algorithm中的函数
8.set
9.iterator inserter
首先要包含#include<iterator>
如以下程序:
vector<int> filter (const vector<int> &vec,const int val,less<int> &pred){
vector<int> ::iterator first=vec.begin();
vector<int>::iterator last=vec.end();
vector<int> nvec;
vector<int> ::iterator at=nvec.begin();
while((first=find_if(first,last,bind2nd(pred,val))) !=last){
*at++=*first++;
}
}
这个filter函数采取的方式是,将符合条件的每一个元素一一赋值给一个新的vector,而不是push_back,因此这个新的vector的尺寸我们并不知道,而在程序中取地址at时,通过at++遍历vector的每一个存储空间,又因为每个固定vector的大小,所以可能会出错。我们必须要保证vector足够大。
因此标准库提供了insertion adapter,避免使用容器的assignment 运算符。
- back_inserter()
以容器的push_back代替assignment运算符
list<int> lst = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
copy(lst.begin(), lst.end(), back_inserter(lst2));
//lst2包含10,1,2,3,4,5,6,7,8,9
将lst中的元素插入到lst2中
- inserter()
list<int> lst = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
copy(lst.cbegin(), lst.cend(), inserter(lst3, lst3.begin()));
//lst3包含1,2,3,4,5,6,7,8,9,10
将lst插入到lst3指定位置之前
- front_inserter
list<int> lst = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
list<int> lst4={10};
copy(lst.cbegin(), lst.cend(), front_inserter(lst4));
//lst4包含9,8,7,6,5,4,3,2,1,10
将每个元素一次插入到lst4第一个元素前
10.iostream iterator
标准库定义的iostream iterator,包括istream_iterator 和 ostream_iterator,分别支持单一类型的元素读取和写入
#include<iterator>
#include<iostream>
#include<iterator>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
int main(){
//提供一个first iterator,将is定义为标准输入
istream_iterator<string> is(cin);
//同时还要有last iterator,表示要读取的最后一个元素的下一位置
istream_iterator<string> eof;
vector<string> text;
//通过copy,将cin到eof的元素插入到text中
copy(is,eof,back_inserter(text));
sort(text.begin(),text.end());
//定义一个输出,将text的元素复制给os 即标准输出cout,同时还有空格
ostream_iterator<string> os(cout," ");
copy(text.begin(),text.end(),os );
}
在实现标准输入输出的同时,还可以从文件中读取,并写入到文件中
#include<iostream>
#include<iterator>
#include<fstream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
int main(){
ifstream in_file("input_file.txt");
ofstream out_file("output_file.txt");
istream_iterator<string> is(in_file);
istream_iterator<string> eof;
vector<string> text;
copy(is,eof,back_inserter(text));
sort(text.begin(),text.end());
ostream_iterator<string> os(outfile," ");
copy(text.begin(),text.end(),os );
}