C++ Primer第十章!
#include "stdafx.h"
#include
#include
#include
#include //泛型算法
#include
#include //back_inserter插入迭代器
#include //调用标准库bind函数
using namespace std;
using namespace std::placeholders; //使用名字_n,bind函数时使用!
bool check_size(const string &s, string::size_type sz)//下标是size_t,容器是size_type
{
return s.size() >= sz;
}
int main()
{
//只读容器元素值
//泛型算法find。泛型算法本身不会执行容器的操作,他们只运行在迭代器上,执行迭代器的操作!
int val = 12;
vector vec_find = { 1,2,3,12 };
auto result_int = find(vec_find.cbegin(), vec_find.cend(), val); //如果找到则返回指向迭代器,如果没找到则返回第二个实参cend!
int sum = accumulate(vec_find.cbegin(), vec_find.cend(), 0); //求和算法,第3个参数决定和的初值及类型。
//find操作迭代器,所以find函数可以在任何容器中查找值!泛型算法!
string val_find_string( "aa ab");
vector string_find = {"a","aa ab","c"};
auto result_str = find(string_find.cbegin(), string_find.cend(), val_find_string);
//equal操作,元素必须支持==比较。如果对应元素都相等,则返回true!
//equal(c1.cbegin(),c1.cend(),c2.cbegin()); 只接受一个迭代器表示第二个容器的算法,都假定第二个容器至少与第一个容器一样长!
//改变容器元素值,泛型算法只能改变元素值,但不能直接添加删除元素!
//fill操作,fill(c1.begin(),c1.end(),10),将迭代器范围内元素重置为10.
//fill_n操作,fill(c1.begin(),c1.size(),10), 向空容器中用fill写入元素是灾难行为,普通迭代器只能遍历容器!
//插入迭代器back_inserter,插入迭代器可以向容器中添加元素!普通迭代器只能遍历元素,无法添加!
vector vec_back_iter;
auto it = back_inserter(vec_back_iter);
*it = 520; //向容器中添加元素值为520
//与fill_n算法使用
fill_n(back_inserter(vec_back_iter), 9, 10);//在每步迭代中,fill_n向back_inserter创建的元素赋值!
//拷贝算法
int a1[] = { 1,2,3,4,5 };
int a2[sizeof(a1) / sizeof(*a1)];
auto ret = copy(begin(a1), end(a1),begin(a2)); //必须确保a2数组至少要包含a1数组一样多的元素!返回拷贝值之后的位置!
replace(begin(a1), end(a1), 3, 10); //将数组a1中等于3的元素值改为10!
vector vec_rep;
replace_copy(begin(a1), end(a1), back_inserter(vec_rep), 3, 10); //保留原序列,并拷贝原序列同时将3改为10!
//重排容器元素的算法
vector vec_sort_unique = { "hello","world","!","hello","honey","!" };
sort(vec_sort_unique.begin(), vec_sort_unique.end()); //排序算法,元素必须可以比较(<)!
auto end_unique = unique(vec_sort_unique.begin(), vec_sort_unique.end()); //返回不重复值范围末尾的迭代器!
vec_sort_unique.erase(end_unique, vec_sort_unique.end()); //调用容器erase操作,删除重复元素!
//定制操作,为算法定义自己的操作,分为一元谓词和二元谓词
vector string_predicate = { "the","quick","red","fox","jumps","over","the","slow","red","turrie" };
cout << "The oldd string:";
for (auto &r : string_predicate)
{
cout << r << " ";
}
cout << endl;
sort(string_predicate.begin(), string_predicate.end());
cout << "The new1 string:";
for (auto &r : string_predicate)
{
cout << r << " ";
}
cout << endl;
stable_sort(string_predicate.begin(), string_predicate.end(), [](const string &a, const string &b) {return a.size() < b.size(); }); //sort和stable_sort,stable_sort稳定排序算法,按照长度排序(且保证之前的字典排序!)(二元谓词,lambda表达式!)
cout << "The new2 string:";
for (auto &r : string_predicate)
{
cout << r << " ";
}
cout << endl;
//lambda,使用捕获列表,捕获sz值!(可以有引用捕获和值捕获,但是应该尽量避免捕获指针或引用)
string::size_type sz = 4;
auto string_find_if = find_if(string_predicate.begin(), string_predicate.end(), [](string &a) {return a.size() > 4; });
//同上等价形式,使用bind给函数绑定实参!auto string_find_bind=find_if(string_predicate.begin(), string_predicate.end(), bind(check_size,_1,sz));
//auto g=bind(f,a,b,_2,c,_1),从而g(x,y)相当于f(a,b,y,c,x)! bind默认为拷贝参数,要想得到引用须使用ref()函数,如ref(os)!
cout << *string_find_if << endl; //find_if返回第一个使谓词结果非0的元素迭代器,如果不存在这样的元素则返回尾后迭代器!
//lambda捕获方式
//[] 空捕获列表
//[names] 名字列表,如果加上&则为引用捕获方式
//[&] 隐式捕获列表,采用引用捕获方式
//[=] 隐式捕获列表,采用值捕获方式
//[&,identifier_list] [=,identifier_list]
//可变lambda,值捕获通过声明mutable,值引用取决于变量本身是否const
size_t vl_lambda = 13;
auto f = [=]()mutable{return ++vl_lambda; }; //值捕获,相当于拷贝,如果想修改值捕获对象,则需要声明mutable!
vl_lambda = 0;
cout << vl_lambda << " " << f()< vec_lambda = { 1,-2,3,-4,5 };
transform(vec_lambda.begin(), vec_lambda.end(), vec_lambda.begin(), [](int i)->int {if(i < 0) return -i; else return i; }); //指定输出类型为int!
for (auto &r : vec_lambda)
{
cout << r << " ";
}
cout << endl;
//再探迭代器
//插入迭代器 绑定在容器上,向容器插入元素
//流迭代器 绑定到输入或输出流上,可用来遍历关联的IO流
//反向迭代器 迭代器向后移动,除了forward_list之外的标准容器都有反向迭代器
//移动迭代器 移动元素
//插入迭代器分为back_inserter(push_back)、front_inserter(push_front)、inserter,使用形式auto it=back_inserter(vector容器),*it=42!
//流迭代器,istream_iterator为读取输入流,ostream_iterator为向输出流写数据
vector vec_iterator;
istream_iterator in_iter(cin);
istream_iterator eof;
while (in_iter != eof) //流迭代器从cin读取int值,直到遇到eof(被当作尾后迭代器)退出循环!(当遇到文件尾或遇到IO错误,迭代器的值就与尾后迭代器相等)
{
vec_iterator.push_back(*in_iter++);
}
//等价于vector vec(in_iter,eof)
vector vec_out_iter = { 1,2,3,4,5 };
ostream_iterator out_iter(cout, " "); //在每个输出值后添加“ ”!
for (auto e : vec_out_iter)
{
*out_iter++ = e; //(*和++实际上不做任何事情)
}
cout << endl;
copy(vec_out_iter.begin(), vec_out_iter.end(), out_iter); //同上,输出vector中元素!
cout << endl;
//反向迭代器,除了forward_list,其余容器都支持反向迭代器,可以使用rbegin等获取反向迭代器!(迭代器的范围都是[b,e))
string str_line = "FIRST,MIDDLE,LAST";
auto rcomma = find(str_line.crbegin(), str_line.crend(), ','); //find查找对象为string中的字符','!返回迭代器!
cout << string(str_line.crbegin(),rcomma)<