C++ Primer5 第十章 学习笔记

10.2、初识泛型算法

1、只读算法


//对vec中的元素求和,和的初值是0,头文件是numeric
int sum = accumulate(vec.cbegin(), vec.cend(), 0);

//将vector中所有的string元素连接起来
string sum = accumulate(v.cbegin(), v.cend(), string(""));

//equal用于确定两个序列是否保存相同的值,第二个序列元素数目至少应该与第一个一样多
equal(roster1.cbegin(), roster1.cend(), roster2.cbegin());

2、写容器元素的算法

//将每个元素重置为0
fill(vec.begin(), vec.end(), 0);

vector<int> vec;
fill_n(vec.begin(), vec.size(), 0);//将所有元素重置为0,不可指定大小,算法不检查写操作
fill_n(back_inserter(vec), 10, 0);  //添加10个元素到vec

back_inserter接受一个指向容器的引用,返回一个与该容器绑定的插入迭代器。头文件iterator

int a1[] = {0,1,2,3,4,5,6,7,8,9};
int a2[sizeof(a1)/sizeof(*a1)]; //a2与a1大小一样
//ret指向拷贝到a2的尾元素之后的位置
auto ret = copy(begin(a1), end(a2), a2); //把a1的内容拷贝给a2
//将所有值为0的元素改为42
replace(ilist.begin(), ilist.end(), 0, 42);
//使用back_inserter按需要增长目标序列
replace_copy(ilist.cegin(), ilist.cend(), back_inserter(ivec), 0, 42);
//此调用后,ilist并未改变,ivec包含ilist的一份拷贝,不过原来在ilist中值为0的元素改为42

3、重排容器元素的算法

//练习10.9 
#include<iostream>
#include<fstream>
#include<vector>
#include<string>
#include<algorithm>

using namespace std;

inline void output_words(vector<string> &words) //输出
{
    for(auto iter = words.begin(); iter != words.end(); iter++)
        cout << *iter << " ";
    cout << endl;
}

void elimDups(vector<string> &words)
{
    output_words(words);

    sort(words.begin(), words.end());       //按字典序排序,以便查找重复单词
    output_words(words);

    //unique重排输入范围,使得每个单词只出现一次
    //排列在范围前部,返回指向不重复区域之后一个位置的迭代器
    auto end_unique = unique(words.begin(), words.end());
    output_words(words);

    //使用向量操作erase删除重复单词
    words.erase(end_unique, words.end());
    output_words(words);
}

int main(int argc, char *argv[])
{
    ifstream in(argv[1]);
    if(!in){
        cout << "打开输入文件失败!" << endl;
        exit(1);
    }

    vector<string> words;
    string word;
    while(in >> word)
        words.push_back(word);
    
    elimDups(words);

    return 0;
}

10.3 定制操作

1、向算法传递函数

stable_sort 稳定排序算法,可以维持相等元素的原有顺序。

//练习10.13
#include<iostream>
#include<fstream>
#include<vector>
#include<string>
#include<algorithm>

using namespace std;

inline void output_words(vector<string>::iterator beg, vector<string>::iterator end) //输出
{
    for(auto iter = beg; iter != end; iter++)
        cout << *iter << " ";
    cout << endl;
}

bool five_or_more(const string &s1)   //找出大于5的string,返回true
{
    return s1.size() >= 5;
}

int main(int argc, char *argv[])
{
    ifstream in(argv[1]);
    if(!in){
        cout << "打开输入文件失败!" << endl;
        exit(1);
    }

    vector<string> words;
    string word;
    while(in >> word)
        words.push_back(word);
    output_words(words.begin(), words.end());
    //partition接受一个谓词,对容器内容进行划分,true排在容器的前半部分,false排在后半部分
    auto iter = partition(words.begin(), words.end(), five_or_more);
    output_words(words.begin(), words.end());

    return 0;
}

2、lambda表达式

可调用对象,函数、函数指针、重载了函数调用运算符的类、lambda表达式。

一个lambda表达式表示一个可调用的代码单元,可理解为一个未命名的内联函数。

[capture list] (parameter list) -> return type {function body}

参数列表和返回类型可忽略,必须包含捕获列表(一个lambda所在函数中定义的局部变量的列表)和函数体。

//第三个参数为lambda表达式,实现isShorter的功能
stable_sort(words.begin(), words.end(), [](const string &a, const string &b)
                                            { return a.size() < b.size();});

上面空的捕获列表表明此lambda表达式不使用它所在函数中的任何局部变量。

//练习10.16
#include<iostream>
#include<fstream>
#include<vector>
#include<string>
#include<algorithm>

using namespace std;

inline void output_words(vector<string> &words) //输出
{
    for(auto iter = words.begin(); iter != words.end(); iter++)
        cout << *iter << " ";
    cout << endl;
}

void elimDups(vector<string> &words)
{
    sort(words.begin(), words.end());       //按字典序排序,以便查找重复单词
    output_words(words);

    //unique重排输入范围,使得每个单词只出现一次
    //排列在范围前部,返回指向不重复区域之后一个位置的迭代器
    auto end_unique = unique(words.begin(), words.end());

    //使用向量操作erase删除重复单词
    words.erase(end_unique, words.end());
}

string make_plural(size_t ctr, const string &word, const string &ending)
{
    return (ctr > 1) ? word + ending : word;
}

void biggies(vector<string> &words, vector<string>::size_type sz)
{
    elimDups(words);            //将words按字典序排序,删除重复单词
    //按长度排序,长度相同的单词维持字典序
    stable_sort(words.begin(), words.end(), 
                [](const string &a, const string &b)
                  { return a.size() < b.size(); });
    //获取一个迭代器,指向第一个满足size() >= sz的元素
    auto wc = find_if(words.begin(), words.end(), [sz](const string &a)
                                                  { return a.size() >= sz; });
    //计算满足size >= sz的元素的数目
    auto count = words.end() - wc;
    cout << count << " " << make_plural(count, "word", "s")
         << " of length " << sz << " or longer" << endl;
    //打印长度大于等于给定值的单词,每个单词后面接一个空格
    for_each(wc, words.end(), [](const string &s){cout << s << " ";});
    cout << endl;
}

int main(int argc, char *argv[])
{
    ifstream in(argv[1]);
    if(!in){
        cout << "打开输入文件失败!" << endl;
        exit(1);
    }

    vector<string> words;
    string word;
    while(in >> word)
        words.push_back(word);
    
    biggies(words, 4);

    return 0;
}

3、lambda捕获和返回

值捕获:与参数不同,被捕获的变量的值是在lambda创建时拷贝,而不是调用时拷贝。

引用捕获:当以引用方式捕获一个变量时,必须保证在lambda执行时变量是存在的。

隐式捕获:&隐式引用捕获,=隐式值捕获,显式捕获可以和隐式捕获混合使用

可变lambda:值捕获的方式可以加mutable改变值,引用捕获取决于是否const

指定lambda返回类型:使用尾置返回类型

4、参数绑定

标准库bind函数:   auto newCallable = bind(callable, arg_list)    newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的callable的参数。   arg_list参数可能包含形如_n的名字,n为整数,这些参数是“占位符”。数值n表示生成的可调用对象中参数的位置。头文件 functional。   

//练习10.22
#include<iostream>
#include<fstream>
#include<vector>
#include<string>
#include<algorithm>
#include<functional>

using namespace std;
using namespace std::placeholders;

inline void output_words(vector<string> &words) //输出
{
    for(auto iter = words.begin(); iter != words.end(); iter++)
        cout << *iter << " ";
    cout << endl;
}

bool check_size(const string &s, string::size_type sz)
{
    return s.size() >= sz;
}

string make_plural(size_t ctr, const string &word, const string &ending)
{
    return (ctr > 1) ? word + ending : word;
}

void biggies(vector<string> &words, vector<string>::size_type sz)
{
    output_words(words);
    
    //计算满足size >= sz的元素的数目
    //count_if:接受一对迭代器,和一个谓词,返回一个计数值,表示谓词有多少次为真。
    auto bc = count_if(words.begin(), words.end(), bind(check_size, _1, sz));
    cout << bc << " " << make_plural(bc, "word", "s")
         << " of length " << sz << " or longer" << endl;
}

int main(int argc, char *argv[])
{
    ifstream in(argv[1]);
    if(!in){
        cout << "打开输入文件失败!" << endl;
        exit(1);
    }

    vector<string> words;
    string word;
    while(in >> word)
        words.push_back(word);
    
    biggies(words, 6);

    return 0;
}

10.4、再探迭代器

1、插入迭代器

back_inserter    front_inserter    inserter

2、iostream迭代器

 

3、反向迭代器

流迭代器和forward_list不支持创建反向迭代器。

//10.37给定一个包含10个元素的vector,将位置3到7之间的元素按逆序拷贝到一个list中
#include<iostream>
#include<vector>
#include<algorithm>
#include<list>
#include<iterator>

using namespace std;

int main()
{
    vector<int> vi = {0,1,2,3,4,5,6,7,8,9};
    ostream_iterator<int> out_iter(cout, " ");

    copy(vi.cbegin(), vi.cend(), out_iter);
    cout << endl;

    list<int> li;
    vector<int>::reverse_iterator re(vi.begin() + 2);
    vector<int>::reverse_iterator rb(vi.begin() + 7);

    copy(rb, re, back_inserter(li));
    copy(li.begin(), li.end(), out_iter);
    cout << endl;

    return 0;
}

10.5、泛型算法结构

1、5类迭代器

2、算法形参模式

10.6、特定容器算法

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值