chapter-10

C++ Primer第十章!

#include "stdafx.h"
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>         //泛型算法
#include<numeric>           
#include<iterator>          //back_inserter插入迭代器
#include<functional>        //调用标准库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<int> 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> 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<int> 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<int> vec_rep;
    replace_copy(begin(a1), end(a1), back_inserter(vec_rep), 3, 10);    //保留原序列,并拷贝原序列同时将3改为10!

    //重排容器元素的算法
    vector<string> 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> 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()<<endl;

    vector<int> 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<int> vec_iterator;
    istream_iterator<int> in_iter(cin);
    istream_iterator<int> eof;
    while (in_iter != eof)                  //流迭代器从cin读取int值,直到遇到eof(被当作尾后迭代器)退出循环!(当遇到文件尾或遇到IO错误,迭代器的值就与尾后迭代器相等)
    {
        vec_iterator.push_back(*in_iter++);
    }
    //等价于vector<int> vec(in_iter,eof)
    vector<int> vec_out_iter = { 1,2,3,4,5 };
    ostream_iterator<int> 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)<<endl;
    cout << string(rcomma.base(),str_line.cend()) << endl;              //reverse_iterator调用base成员函数,返回其对应的普通迭代器!
    
    //链表类型容器list和forward_list,应优先使用成员函数版本的算法!
        //list提供双向迭代器,forward_list提供前向迭代器。链表的独有方法与通用版有所不同,如unique会删除相同元素,而通用版本不会!
    //lst.merge(lst2)           将lst2并入lst,合并后lst2为空。
    //lst.merge(lst2,comp)
    //lst.remove(val)           删除元素(或满足条件的元素)
    //lst.remove_if(pred)
    //lst.reverse()             反转lst中的元素
    //lst.sort()                使用<或给定操作排序元素
    //lst.sort(comp)
    //lst.unique()              
    //lst.unique(pred)
    //splice和splice_after(args) args可以为p,lst2/p,lst2,p2/p,lst2,b,e将lst2的元素移动到lst中!

    system("pause");
    return 0;
}

//标准库并未给每个容器添加大量功能,而是提供一组算法,泛型算法!
//大多数算法都定义在头文件algorithm,标准库还在头文件numeric中定义了一组数值泛型算法。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容