c++ primer(第五版)笔记 第九章 顺序容器(2)

时间:2023-02-13 20:31:45
// 顺序容器
// 添加元素(array 除外)
// 在尾部创建一个值为 t 或由 args 创建的元素,返回 void,不支持 forward_list
// c.push_back(t)
// c.emplace_back(args)

// 在头部创建一个值为 t 或由 args 创建的元素,返回 void,不支持 vector 和 string
// c.push_front(t)
// c.emplace_front(args)

// 在迭代器 p 指向的元素之前创建一个值为 t 或由 args 创建的元素,返回新添加的元素迭代器
// forward_list有自身独有的 insert 和 emplace
// c.insert(p,t)
// c.emplace(p,args)

// 在迭代器 p 指向的元素之前插入 n 个值为 t 的元素,返回指向新添加的第一个元素的迭代器,若 n 为 0,返回 p
// c.insert(p,n,t)

// 在迭代器 p 指向的元素之前插入迭代器 b,e 指定范围内的元素,返回指向新添加的第一个元素的迭代器,若 n 为 0,返回 p,b,e 不能指向 c 中的元素
// c.insert(p,b,e)

// 在迭代器 p 指向的元素之前插入元素值列表 {li},返回指向新添加的第一个元素的迭代器,若 n 为 0,返回 p
// c.insert(p,li)

// 向 vector deque string 插入一个元素,会使指向该容器的迭代器,指针,引用失效
// 向 vector string 尾部之外的位置,deque 头尾之外的位置插入元素,都需要移动元素
// 而且向 vector string 添加元素还可能引起对整个对象存储空间的重新分配

//容器访问
//所有容器,包括 array 都有一个 front 成员函数,返回首元素的引用
//除 forward_list 外,所有容器都一个 back 成员函数,返回尾元素的引用
//如果为空,函数行为是未定义的
// string vector deque array 提供下标运算,下标是无符号整数,如果大于等于容器大小,是未定义行为
//at 成员函数类型下标运算,但如果下标越界,会抛出 out_of_range 的异常

// 删除元素(array 除外)
// 删除尾元素,若 c 为空,行为未定义,返回 void,不支持 forward_list
// c.pop_back()

// 删除首元素,若 c 为空,行为未定义,返回 void,不支持 vector 和 string
// c.pop_front()

// forward_list 有自己版本的 erase
// 删除迭代器 p 指向的元素,返回一个指向被删除元素之后的元素的迭代器,若 p 指向尾元素,返回尾后迭代器,若 p 是尾后迭代器,行为未定义
// c.erase(p);

// 删除 b,e 迭代器范围内的元素,返回一个指向最后一个被删除元素之后的元素的迭代器,若 e 是尾后迭代器,则返回尾后迭代器
// c.earse(b,e);

// 删除所有元素,返回 void
// c.clear();

// 删除 deque 首尾位置之外的元素,会使所有迭代器,指针,引用失效
// 删除 vector string 中的元素,指向删除点之后位置的迭代器,指针,引用失效

// forward_list 操作
// 返回指向首元素之前不存在的元素的迭代器,不可以解引用
// c.before_begin()

// 返回指向首元素之前不存在的元素的 const 迭代器,不可以解引用
// c.cbefore_begin()

// 在迭代器 p 之后的位置插入,若 p 是 off of end 迭代器,行为未定义
// c.insert_after(p,t)
// c.insert_after(p,n,t)
// c.insert_after(p,b,e)
// c.insert_after(p,li)

// 在 p 后插入一个用 args 构建的元素,返回这个新元素的迭代器,若 p 是 off of end 迭代器,行为未定义
// c.emplace_after(p,args)

// 删除 p 位置之后的元素或者从 b 之后到(不包括)e之间的元素,返回删除元素之后元素的迭代器,若 p 是尾元素迭代器或 off of end 迭代器,行为未定义
// c.erase(p)
// c.erase(b,e)

// 改变容器大小,会导致迭代器失效
// 调整 c 的大小为 n 个元素,若 n < c.size(),多出的元素被丢弃,若需要添加新元素,对新元素执行值初始化
// c.resize(n)

// 调整 c 的大小为 n 个元素,所有新加元素初始化为 t
// c.resize(n,t)

// 容器操作对迭代器的影响
// 添加元素
// 1>如果是 vector string,且存储空间被重新分配,则指向容器的所有迭代器,指针,引用都会失效
// 如果未重新分配空间,则指向插入位置前的元素迭代器,指针,引用仍有效,之后的均失效

// 2>如果是 deque,在首尾之外位置插入元素,会导致指向容器的所有迭代器,指针,引用失效
// 如果在首尾插入元素,迭代器会失效,指针,引用仍然有效

// 3>如果是 list forward_list ,无影响,均有效

// 删除元素,被删除的元素的迭代器,指针,引用失效
// 1>对于 list forward_list 其他位置的元素,无影响,均有效
// 2>对于 vector string,指向被删元素之前的迭代器,指针,引用仍有效,但尾后迭代器总是失效
// 3>对于 deque,如果在首尾之外的位置删除元素,那么其他位置的迭代器,指针,引用都会失效
// 如果是删除尾元素,则尾后迭代器失效,其他无影响,如果是首元素,也无影响

#include<stdexcept>
#include<string>
#include<iostream>
#include<deque>
#include<list>
#include<vector>
#include<forward_list>

using std::out_of_range;
using std::string;
using std::list;
using std::vector;
using std::forward_list;
using std::deque;
using std::cout;
using std::cin;
using std::endl;

void practice_918();
void practice_919();
void practice_924();
void practice_925();
void practice_926();
void practice_927();
void practice_928(forward_list<string> &fi, string &sa, string &sb);

int main()
{
// practice_918();
// practice_919();
// practice_924();
// practice_925();
// practice_926();
// practice_927();

forward_list<string> fs{"hello", "world", "mamamia", "bye"};
string sa{"wold"};
string sb{"i'm coming"};
practice_928(fs, sa, sb);
return 1;
}
//从流中读入string, 压入 deque 或 list
void practice_918()
{
//写入
string stmp;
deque<string> ds;
list<string> ls;
while(cin >> stmp)
{
// ds.push_back(stmp);
ls.push_back(stmp);
}
//输出
// auto di = ds.cbegin();
auto di = ls.cbegin();
// while(di != ds.cend())
while(di != ls.cend())
{
cout << *di << endl;
++di;
}
}
// 将 list<int> 中元素,按奇偶压入 2个deque
void practice_919()
{
list<int> li{234,1327,8254,9123,823,753,18,37,74,398,1};
deque<int> di_even, di_odd;
auto lii = li.cbegin();
while(lii != li.cend())
{
if(!(*lii % 2 ))
di_even.push_front(*lii);
else
di_odd.push_front(*lii);
++lii;
}
for(auto i : di_even)
cout << "di_even:" << i << endl;
for(auto i : di_odd)
cout << "di_odd:" << i << endl;
}
//顺序容器的访问
void practice_924()
{
deque<int> vi{234,1327,8254,9123,823,753,18,37,74,398,1};
cout << "vi.first = " << vi.front() << endl;
cout << "vi.first = " << *(vi.begin()) << endl;
cout << "vi.first = " << vi[0] << endl;
cout << "vi.first = " << vi.at(0) << endl;
vi.clear();//清空
try
{
cout << "vi.first = " << vi.at(0) << endl;
}
catch(out_of_range err)//捕捉 out_of_range 异常
{
cout << "vi is empty" << endl;
}
cout << "vi.first = " << vi[0] << endl;//未定义行为
}
//删除容器元素
void practice_925()
{
deque<int> vi{234,1327,8254,9123,823,753,18,37,74,398,1};

deque<int>::iterator fi = vi.begin() + 3;
deque<int>::iterator ei = vi.begin() + 5;
auto res = vi.erase(fi,ei);
cout << "result of erase = " << *res << endl;
for(auto i : vi)
cout << "i : vi = " << i << endl;

cout << "******************" << endl;
// 如果 erase 传入2个相等的迭代器,不会删除元素,该迭代器
fi = vi.begin() + 3;
ei = vi.begin() + 3;
res = vi.erase(fi,ei);
cout << "result of erase = " << *res << endl;
for(auto i : vi)
cout << "i : vi = " << i << endl;

cout << "******************" << endl;
// 如果 erase 传入2个尾后的迭代器,不会删除元素,该尾后迭代器
fi = vi.end();
ei = vi.end();
res = vi.erase(fi,ei);
if(res == vi.end())
cout << "result of erase is off of end! " << endl;
for(auto i : vi)
cout << "i : vi = " << i << endl;
}

//删除容器元素
void practice_926()
{
int ai[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
list<int> li(ai, ai + sizeof(ai) / sizeof(int));
vector<int> vi(ai, ai + sizeof(ai) / sizeof(int));

for(auto i : li)
cout << i << " - ";
cout << endl;
for(auto i : vi)
cout << i << " - ";
cout << endl;
cout << "******************" << endl;
//按奇偶删除元素
for(auto ii = li.begin(); ii != li.end();)
{
if(*ii % 2)
++ii;
else
ii = li.erase(ii);
}
for(auto ii = vi.begin(); ii != vi.end();)
{
if(*ii % 2)
ii = vi.erase(ii);
else
++ii;
}
cout << "******************" << endl;
for(auto i : li)
cout << i << " - ";
cout << endl;
for(auto i : vi)
cout << i << " - ";
cout << endl;
}

//从 forward_list 中删除元素
void practice_927()
{
int ai[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
forward_list<int> fi(ai, ai + sizeof(ai) / sizeof(int));

auto fii = fi.begin();
auto bfii = fi.before_begin();
while(fii != fi.end())
{
if(*fii % 2)
{
fii = fi.erase_after(bfii);
}
else
{
bfii = fii;
++fii;
}
}
cout << "******************" << endl;
for(auto i : fi)
cout << i << " - ";
cout << endl;
}

//在 forward_list 中查找 sa,将sb 插入其后,若找不到 sa,将sb 插到末尾
void practice_928(forward_list<string> &fi, string &sa, string &sb)
{
auto fii = fi.begin();
auto bfii = fi.before_begin();
while(fii != fi.end())
{
if(*fii == sa)
{
fii = fi.insert_after(fii,sb);
break;
}
else
{
bfii = fii;
++fii;
}
}
if(fii == fi.end())
fi.insert_after(bfii, sb);

cout << "******************" << endl;
for(auto i : fi)
cout << i << " - ";
cout << endl;
}