chapter-10

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)<

你可能感兴趣的:(chapter-10)