《c++ primer》 第10章 课后练习(一)

练习 10.1 头文件algorthm中定义了一个名为count的函数,它类似于find,接受一对迭代器和一个值作为参数。count返回定值出现的次数。编写程序,读取int序列存入vector中,打印有多少个元素值等于定值。

    vector<int> ivec;
     int i ;
     while(cin >> i)
         ivec.push_back(i);
     int n1 = count(ivec.begin(),ivec.end(),1);
     cout<< n1;

练习 10.2 重做上一题,但读取string序列存入list中。

     vector<string> ivec;
     string i ;
     while(cin >> i)
         ivec.push_back(i);
     int n1 = count(ivec.begin(),ivec.end(),"is");
     cout<< n1;

练习10.3:用accumulate求一个vector<int>中的元素之和。

     vector<int> ivec{1,2,3,4,5,6,7,8,9};
     cout<<accumulate(ivec.cbegin(),ivec.cend(),0);

练习10.4 假定 v 是一个vector,那么调用 accumulate(v.cbegin(),v.cend(),0) 有何错误(如果存在的话)?

     vector<double> ivec{1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9};
     cout<<accumulate(ivec.cbegin(),ivec.cend(),0);

默认为int操作,计算精度降低。

练习10.5 在本节对名册(roster)调用equal 的例子中,如果两个名册中保存的都是C风格字符串而不是string,会发生什么?

如果是c风格的话,equal会比较指向的地址,而不是字符串的值。

练习10.6 编写程序,使用full_n将一个序列中的int值都设置为0。

     vector<int> ivec={123,13,5,8,123,0};
     fill_n(ivec.begin() , ivec.size(),0);
    for (auto i: ivec) {
        cout<<i<<' ';

    }

练习10.7 下面程序是否有错误?如果有,请改正。

a) vector<int> vec; list<int> lst; int i;
        while(cin>>i)
            lst.push_back(i);
        copy(lst.cbengin(),lst.cend(),vec.begin());
b) vector<int> vec;
    vec.reserve(10);
    fill_n(vec.begin(), 10 , 0);

对于a)来说,vec是空的,而算法不会给他开辟空间,算法永远不会改变底层的大小,所以这个地方要用back_inserter,插入迭代器来给vec赋值。

vector<int> vec; list<int> lst = {1,2,3,4}; int i;
//    while(cin>>i)
//        lst.push_back(i);
    copy(lst.begin(),lst.end(), back_inserter(vec));
    for (auto i: vec) {
        cout << i << ' ';

    }

对于b)来说reserve之后vec的大小还是0;所以将reserve改为resize,或者使用插入迭代器。

    vector<int> vec;
    vec.resize(10);
    fill_n(vec.begin(), 10 , 0);



    vector<int> vec;
    vec.resize(10);
    fill_n(back_inserter(vec), 10 , 0);

练习10.8 本节提到过,标准库算法不会改变它们所操作的容器的大小。为什么使用back_inserter不会使这一断言失效?

inserter不是隶属于algorithm,而是属于iterator头文件,所以这一断言没有失效,并且back_inserter这个迭代器配合algorithm头文件的里的算法有更灵活的使用。

练习10.9 实现你自己的elimDups。测试你的程序,分别在读取输入后、调用unique后以及调用erase后打印vector的内容。

void elimDups(vector<string> &words){
    for (auto s: words) {
        cout<<s<<' ';
    }
    cout<<endl;
    sort(words.begin(),words.end());
    vector<string>::iterator end_unique = unique(words.begin(),words.end());
    for (auto s: words) {
        cout<<s<<' ';
    }
    cout<<endl;
    words.erase(end_unique,words.end());
}

练习10.10 你认为算法不改变容器大小的原因是什么?

@Mooophy:
这种设计的目的是将算法和成员函数提供的操作分开。

@pezy:
因为库算法在迭代器上运行,而不是在容器上运行。因此,算法不能(直接)添加或删除元素。

练习10.11 编写程序,使用stable_sort和isShort将传递给你的elimDups版本的vector排序。打印vector的内容,验证你的程序的正确性。

#include <iostream>
#include <vector>
#include <list>
#include <deque>
#include <forward_list>
#include <algorithm>
#include <numeric>
using namespace  std;
void elimDups(vector<string> &words){
    for (auto s: words) {
        cout<<s<<' ';
    }
    cout<<endl;
    sort(words.begin(),words.end());
    vector<string>::iterator end_unique = unique(words.begin(),words.end());
    for (auto s: words) {
        cout<<s<<' ';
    }
    cout<<endl;
    words.erase(end_unique,words.end());
}
bool is_short(const string &s1, const string &s2){
    return s1.size() < s2.size();
}
int main() {
    vector<string> vec = {"a","b","c","d","e","f","g","a","b","d","1234", "1234", "1234", "Hi", "alan", "wang"};
    elimDups(vec);
    stable_sort(vec.begin(),vec.end(), is_short);
    for (auto s: vec) {
        cout<<s<<' ';
    }
    cout<<endl;


    return 0;
}

练习10.13 标准库定义了名为partition的算法,它接受一个谓词,对容器内容进行划分,使得谓词为true的值会排在容器的前半部分,而谓词为false的值会排在后半部分。算法返回一个迭代器,指向最后一个使用谓词为true的元素之后的位置。编写函数,接受一个string,返回一个bool值,指出string是否有5个或更多字符。使用此函数划分words。打印出长度大于等于5的元素。

bool no_short(const string &s){
    return s.size()>= 5;
}
int main() {
    vector<string> vec = {"aaaaa","baaaa","caaa","daaaa","e","f","g","a","b","d","12334", "41234", "ff1234", "Hi", "alan", "wang"};
    vector<string>::iterator end_m = partition(vec.begin(),vec.end(), no_short);
    for (auto it = vec.begin(); it != end_m ; ++it) {
        cout<< *it<<' ';
    }

    return 0;
}

练习10.14 编写一个lambda,接受两个int,返回它们的和。

int main() {
    auto f = [](const int &a, const int &b) -> int{ return a + b;};
    cout<<f(1,2);

    return 0;
}

练习10.15 编写一个lambda,捕获它所在函数的int,并接受一个int参数。lambda应该返回捕获的int和int参数的和。

void tes(){
    int i = 1;
    int j = 3;
    auto f = [i](const int &a) -> int{return i + a;};
    cout<<f(j);

}

练习10.16 使用lambda编写你自己版本的biggies。

void elimDups(vector<string> &words){
    for (auto s: words) {
        cout<<s<<' ';
    }
    cout<<endl;
    sort(words.begin(),words.end());
    vector<string>::iterator end_unique = unique(words.begin(),words.end());
    for (auto s: words) {
        cout<<s<<' ';
    }
    cout<<endl;
    words.erase(end_unique,words.end());
}
void biggies(vector<string> &s,const int &num){
    elimDups(s);
    auto start = find_if(s.begin(),s.end(),[num](const string &a){return a.size() >= num;});
    while(start != s.cend()){
        cout<<*start++<<' ';
    }
}
int main() {
    vector<string> s = {"123","12345","12345","12345","12359067","1235927846"};
    biggies(s,5);
    return 0;
}

练习10.18 重写biggies函数,用partition代替find_if。我们在10.3.1节练习10.13中介绍了partition算法。

void biggies(vector<string> &s,const int &num){
    elimDups(s);
    auto end = partition(s.begin(),s.end(),[num](const string &a){return a.size() >= num;});
    auto it = s.begin();
    while(it != end){
        cout<<*it++<<' ';
    }
}
int main() {
    vector<string> s = {"123","12345","12345","12345","12359067","1235927846"};
    biggies(s,5);
    return 0;
}

练习10.19 用stable_partition 重写前一道题的程序,与stable_sort类似,在划分后的序列中维持原有元素的顺序。

void biggies(vector<string> &s,const int &num){
    elimDups(s);
    auto end = stable_partition(s.begin(),s.end(),[num](const string &a){return a.size() >= num;});
    auto it = s.begin();
    while(it != end){
        cout<<*it++<<' ';
    }
}
int main() {
    vector<string> s = {"123","12345","12345","12345","12359067","1235927846"};
    biggies(s,5);
    return 0;
}

练习10.20 标准库定义了一个名为count_if的算法。类似find_if,此函数接受一对迭代器,表示一个输入范围,还接受一个谓词,会对输入范围中的每个元素执行。count_if返回一个计数值,表示谓词有多少为真。使用count_if重写我们程序中统计多少单词长度超过6的部分。

void elimDups(vector<string> &words){
    for (auto s: words) {
        cout<<s<<' ';
    }
    cout<<endl;
    sort(words.begin(),words.end());
    vector<string>::iterator end_unique = unique(words.begin(),words.end());
    for (auto s: words) {
        cout<<s<<' ';
    }
    cout<<endl;
    words.erase(end_unique,words.end());
}
int main() {
    vector<string> s = {"123","12345","12345","12345","12359067","1235927846"};
    elimDups(s);
    int n = 6;
    auto num = count_if(s.begin(),s.end(),[&n](string &s) -> bool { return s.size() > n;});
    cout<<num;
    return 0;
}

练习10.21 编写一个lambda,捕获一个局部变量int变量,并递减变量值,直至它变为0。一旦变量变为0,再调用lambda应该不再递减变量。lambda应该返回一个bool值,指出捕获的变量是否为0。

int main() {
    vector<string> s = {"123","12345","12345","12345","12359067","1235927846"};
    int i = 6;
    auto temp = [&i] () -> bool { if ((i--) >0) return true ; else return false ; };
    while(temp())
        cout<<i<<' ';
    return 0;
}

练习10.22 重写统计长度小于等于6的单词数量的程序,使用函数代替lambda。

挺简单的就不写了。

练习10.23 bind接受几个参数?

如果函数有n个参数,那么bind有n+1个参数。

练习10.24 给定一个string,使用bind和check_size在一个int的vector中查找第一个大于string长度的值。

using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::find_if;
using std::bind;
using std::size_t;

auto check_size(string const& str, size_t sz)
{
    return str.size() < sz;
}

int main()
{
    vector<int> vec{ 0, 1, 2, 3, 4, 5, 6, 7 };
    string str("123456");
    auto result = find_if(vec.begin(), vec.end(), bind(check_size, str, _1));
    if (result != vec.cend())
        cout << *result << endl;
    else
        cout << "Not found" << endl;

    return 0;
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值