- 范围for语句
- 遍历的对象必须能够使用begin()和end()
- 等价于
for(auto beg=v.begin(),end=v.end();beg!=end;++beg){
…
}
注意范围for语句预存了尾后寄存器,所以注意对于因添加/删除而使尾迭代器失效的容器
for(循环变量:遍历的对象)
如果需要改变遍历的对象
for(auto &c:遍历的对象)
迭代器类别:根据迭代器所提供的操作分类
输入/输出迭代器:
- 只读不写
- 前置/后置递增
- 只能用于单遍扫描算法
- 解引用
输入迭代器:
- 通过迭代器提取元素
- ==/!=
- 例如istream_iterator
输出迭代器:例如copy函数和ostream_iterator
前向迭代器:
- 可读写
- 前置/后置递增
- 可以用于多遍扫描的算法
- 支持输入迭代器和输出迭代器的操作
- 只能沿1个方向
- 例如forward_list的迭代器
双向迭代器:
- 可读写
- 前置/后置递增/减
- 可以用于多遍扫描的算法
- 除forward_list外标准库都支持
随机访问迭代器
- 可读写
- 可以用于多遍扫描的算法
- 支持上述所以迭代器类型的操作
- 大小比较
- 与整数的加减运算
- 迭代器之间的减法(距离)
- 下标运算
迭代器:容器都可以使用迭代器
#include <iterator>
//读写
auto it = s1.begin();
auto it = s1.end();//尾元素的下一个位置
//只读
auto it = s1.cbegin();auto it = s1.cend();
- 迭代器类型
string::iterator//读写
string::const_iterator//只读
vector<int>::iterator//读写
vector<int>::const_iterator//只读
- 通用操作
*iter
//读取元素的成员
iter->mem
(*iter).mem
++iter
--iter//forward_list不支持
由于大部分迭代器没有定义大于或者小于操作,尽量使用下面
iter1==iter2
iter1!=iter2
支持快速随机访问的容器
iter +/- n
iter +=/-= n
iter1-iter2
/*大小比较*/
adaptor(适配器)
- 作用:使某种事物看起来像另一种
- 分类
- 容器适配器
- 要求容器必须有添加/删除/访问尾元素的能力
- 只能使用适配器的操作CP329
- 额外要求CP329
- 分类:
- stack
- queue
- priority_queue
- 构造函数
- 容器适配器
//默认构造函数
stack<int> stk;
//外加容器参数重载容器类型
stack< string,vector<string> > stk;
- 迭代器适配器
- 函数适配器
反向迭代器(图CP363)
- 除forward_list以外
- 注意crend迭代器指向第1个元素的前一位置
- 递增:向后移动
- 递减:向前移动
例如在CP364中需要使用反向迭代器输出string的一部分,由于string该函数没有定义输入反向迭代器的重载版本,所以使用reverse_iterator的base()函数对迭代器进行转换。因为需要保持左闭右开的区间,base()函数将会返回迭代器的下一位置。(图CP364)
插入迭代器
- 插入迭代器通常由插入器创建。
- 插入器接受一个容器,返回一个迭代器
- 插入迭代器被绑定到容器上,可用于向容器插入元素
- 分类:(函数)
- back_inserter(c)
创建使用push_back的迭代器 - front_inserter(c)
创建使用push_front的迭代器 - inserter(c,iter)
创建使用inserter的迭代器,额外接收第2个迭代器参数(元素将会插入到该迭代器之前)
- back_inserter(c)
list<int> lst={1,2,3,4};
list<int> lst1,lst2;
//返回的插入迭代器调用push_front插入元素
copy(lst.cbegin(), lst.cend(), front_inserter(lst1) );
//拷贝完成后lst1的存储顺序为4,3,2,1
copy(lst.cbegin(), lst.cend(), inserter( lst2,lst2.begin() ) );
auto it=insert(lst,iter);
*it=5;
//相当于
it=lst.insert(it,5);
++it;//使it指向原来的元素
string
- 初始化
string str(cp,n)//拷贝指针cp所指向数组的前n个元素
//下标越界时函数未定义
string str(s1,pos)//拷贝s1从下标pos开始的字符
//拷贝s1从下标pos开始的len个字符(len越界时拷贝到最后一个)
string str(s1,pos,len)
//拷贝的char型数组必须以空字符结尾/传递计数值
- substr
- 下标越界时函数未定义
- len越界时拷贝到最后一个
s.substr(pos,n)//返回从pos开始的n个字符
- 通用操作的额外操作
s.insert(pos,args)//在pos(迭代器/下标)
s.erase(pos,len)//删除从pos开始的len个字符
s.assign(args)
- 插入到string的末尾
s.append(args)
- 用args替换前面的范围
- 插入args的长度不需要和前面的范围一致
s.replace(11,3,args);//下标11开始的3个字符
s.replace(b,e,args);
- args的形式
/*只有args支持下列所有版本*/
str //字符串
str,pos,len
b,e
//以上3种不能指向本身
cp//字符数组
cp,len
n,c//n个字符
//初始化列表
- 搜索
- 搜索成功返回类型为string::size_type的下标
- 搜索失败返回static成员string::npos
- 由于返回类型为unsigned型,尽量用unsigned型接收
- args的类型:
//从字符串s的下标pos开始查找
c,pos //字符c
s1,pos //字符串s1
cp,pos //指针cp所指向的字符数组,pos默认为0
cp,pos,n //指针cp所指向的字符数组的前n个字符
s.find(args)//返回第一次出现的位置
s.rfind(args)//返回最后一次出现的位置
s.find_first_of(args)//args中任何1个字符第1次出现的位置
s.find_last_of(args)//args中任何1个字符最后1次出现的位置
//注意返回的不是位置
s.find_first_not_of(args)//第1个不属于args的字符
s.find_last_not_of(args)//最后1个不属于args的字符
- 大小比较
- 返回值为正数/0/负数
- args的类型:
s1
//字符串s从下标pos开始的n个字符
pos,n,s1 //与s1比较
pos,n,s1,pos1,n1 //s1从下标pos1开始的n1个字符比较
//cp同上
s.compare(args)
- 数值转换
to_string(val)
//val可以是任何算术类型
- 函数名为sto+类型缩写
- s的第1个空白字符必须为+/-/0~9
- 转换为整数
stoi(s,p,b)
//p:bao
//b:转换所用基数
- 转换为浮点数
stoi(s,p)
- 加法
string s1="hello "; string s1="world";
s1 += s2;
可以将字面值与string相加(字面值之间不可以直接相加)
string s3="hello"+s2;
- 字符处理 CP82
vector
由于C++要求vector能够快速的在尾部添加元素,所以不需要在初始化时设定容器的大小。所以建议直接定义1个空的vector对象。