首页 > 技术文章 > cppPrimer学习-10th

zongzi10010 2020-01-11 13:34 原文


title: cppPrimer学习10th
date: 2020/1/6 19:35:42
toc: true

cppPrimer学习10th

备忘

  • 只读算法
find
count
accumulate //求和
equal
  • 写容器算法
fill
fill_n  fill_n(v.begin(), v.size(), 0);
// back_inserter(containter) 返回一个插入的迭代器,对他赋值执行push_back
copy
sort
unique
stable_sort


  • 谓词 P344

    mark

  • equal 比较的是==,对于char*的类型实际比较的是char*也就是地址,而对于string来说,有重载==操作符

  • unique删除重复之前需要排序,它只是删除相邻相同的元素

  • 迭代器类别

    输入迭代器:只读,不写;单遍扫描,只能递增。支持==、!=、++、*、->
    输出迭代器:只写,不读;单遍扫描,只能递增。支持++、*
    前向迭代器:可读写,多边扫描,只能递增。支持输入输出迭代器的所有操作。
    双向迭代器:可读写,多遍扫描,可递增递减。除支持前向迭代器的操作外,还支持--。
    随机访问迭代器:可读写,多遍扫描,支持全部迭代器运算。除支持双向操作外,还支持<、<=、>、>=、+、+=、-、-=、迭代器的减法运算符(-)、下标运算符(iter[n], *(iter[n]) )。
    
  • 对于listforward_list,应该使用容器定义的成员函数的算法,因为一方面链表可以直接修改链接达到交换元素的目的,另一方面比如sort需要支持随机访问而链表不支持等 p369

10.1

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

int main(int argc, char const *argv[])
{
    vector<int> v = {1, 2, 3, 4, 5, 6, 3, 8, 9, 3, 5, 5};
    auto findme = count(v.begin(), v.end(), 3);
    cout << findme << endl;
    while (1)
        ;
    return 0;
}

10.2

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

#include "include.h"

int main(int argc, char const *argv[])
{

    list<string> l = {"123", "456", "111", "123", "456", "123"};

    auto has = count(l.begin(), l.end(), "123");
    cout << "123 has " << has << endl;

    while (1)
        ;
    return 0;
}

10.3

10.4

/*用accumulate求一个vector中的元素之和*/
/*假定v是一个vector, 那么调用accumulate(v.cbegin(), v.cend(), 0)有何错误(如果存在)
	返回的是int
*/
#include "include.h"

int main(int argc, char const *argv[])
{
    vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};

    auto sum = accumulate(v.begin(), v.end(), 0);
    cout << sum << endl;

    vector<double> v2 = {1.1, 1.2};
    auto sum2 = accumulate(v2.begin(), v2.end(), (double)0); //或者0.0都可以
    cout << sum2 << endl;

    while (1)
        ;
    return 0;
}

10.5

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

答案: 比较的是迭代器指的地址在使用char* 的类型

equal使用==运算符比较两个序列中的元素。string类重载了==,可比较两个字符串是否长度相等且其中元素对位相等。
而C风格字符串本质是char *类型,用==比较两个char *对象,只是检查两个指针值是否相等,即地址是否相等,而不会比较其中字符是否相同。
所以,只有当两个序列中的指针都指向相同的地址时,equal才会返回true,否则,即使字符串内容完全相同,也会返回false。

原文链接:https://blog.csdn.net/sunhero2010/article/details/49803965


For such case, std::equal is going to compare the address value rather than the string value.
 So the result is not the same as std::string. Try to avoid coding this way.
*/

#include "include.h"

void printAddr(const char *addr)
{
    unsigned int a;

    for (int i = 0; i < 6; i++)
    {
        a = (*(addr + i)) & 0xff;
        cout << a << "  ";
    }
    cout << endl;
}

int main(int argc, char const *argv[])
{
    // const char *s1 = "123456789";
    // const char *s2 = "123456789111111";
    // auto ret = equal(begin(s1), end(s1), begin(s2));
    // cout << ret << endl;

    std::vector<const char *> roster1{"Mooophy", "pezy", "Queequeg"};
    std::list<const char *> roster2{"Mooophy", "pezy", "Queequeg", "shbling", "evan617"};
    std::cout << boolalpha << std::equal(roster1.cbegin(), roster1.cend(), roster2.cbegin()) << endl;

    const char a[3][2] = {"A", "B", "C"};
    const char b[3][2] = {"A", "B", "C"};

    std::vector<const char *> v1(std::begin(a), std::end(a));
    std::list<const char *> v2(std::begin(b), std::end(b));

    cout << "a=" << begin(a) << "----" << end(a) << endl;
    printAddr((const char *)&(*begin(a)));
    cout << "b=" << begin(b) << "----" << end(b) << endl;
    printAddr((const char *)&(*begin(b)));

    std::cout << std::boolalpha
              << std::equal(v1.cbegin(), v1.cend(), v2.cbegin()) << std::endl;

    cout << "v1_address=" << &*v1.begin() << "----" << &*v1.end() << endl;
    cout << "v2_address=" << &*v2.begin() << "----" << &*v2.end() << endl;
    printAddr((const char *)&(*v1.begin()));
    printAddr((const char *)&(*v2.begin()));

    vector<string> v3{"A", "B", "C"};
    vector<string> v4{"A", "B", "C"};

    cout << "v3_address=" << &*v3.begin() << "----" << &*v3.end() << endl;
    cout << "v4_address=" << &*v4.begin() << "----" << &*v4.end() << endl;
    printAddr((const char *)&(*v3.begin()));
    printAddr((const char *)&(*v4.begin()));
    std::cout << std::boolalpha
              << std::equal(v3.cbegin(), v3.cend(), v4.cbegin()) << std::endl;

    while (1)
        ;
    return 0;
}

10.6

/*
编写程序,使用fill_n将一个序列中的int都设置为0
*/

#include "include.h"

int main(int argc, char const *argv[])
{

    vector<int> v = {1, 2, 3, 4, 5, 6, 7};

    fill_n(v.begin(), v.size(), 0);
    print(v);
    while (1)
        ;
    return 0;
}

10.7

/*
下面程序是否有错误?如果有,请改正。
reserve 只是确保当前size<capacity,扩充容量但是不会改变size
*/
#include "include.h"

int main(int argc, char const *argv[])
{
    vector<int> vec;
    list<int> lst;
    int i;
    while (cin >> i)
        lst.push_back(i);

    //-------------------
    vec.reserve(lst.size()); // 虽然不会报错误,但是不会有打印的
    //vec.resize(lst.size());
    copy(lst.cbegin(), lst.cend(), vec.begin());
    print(vec);

    while (1)
        ;

    return 0;
}

10.8

标准库算法不会改变他们所操作的容器的大小。为什么使用back_inserter不会使这一断言失效

标准库算法根本不知道有“容器”这个东西。它们只接受迭代器参数,运行于这些迭代器之上,通过这些迭代器来访问元素。
back_inserter 的迭代器能调用对应的插入算法

10.9

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

#include "include.h"

void elimDups(vector<string> &s)
{
    print(s);
    sort(s.begin(), s.end());
    print(s);
    auto last = unique(s.begin(), s.end());
    print(s);
    s.erase(last, s.end());
    print(s);
}

int main(int argc, char const *argv[])
{
    vector<string> vs = {"999",
                         "123",
                         "456",
                         "123",
                         "777",
                         "999"};

    elimDups(vs);
    while (1)
        ;
    return 0;
}

10.10

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

泛型算法为了实现通用化,识别的是迭代器,改变容器大小会使迭代器失效,泛型算法原则上也不知道容器的存在

10.11

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

#include "include.h"

bool isShorter(const string &a, const string &b)
{
    return a.size() < b.size();
}

void elimDups(vector<string> &s)
{
    print(s);
    sort(s.begin(), s.end());
    print(s);
    auto last = unique(s.begin(), s.end());
    print(s);
    s.erase(last, s.end());
    print(s);

    stable_sort(s.begin(), s.end(), isShorter);
    print(s);
}

int main(int argc, char const *argv[])
{
    vector<string> vs = {"9990000",
                         "123000000000",
                         "456",
                         "123000000000",
                         "777",
                         "9990000"};

    elimDups(vs);
    while (1)
        ;
    return 0;
}

10.12

//编写名为compareIsbn的函数,比较两个Sales_data对象的isbn()成员。使用这个函数排序一个保存Sales_data对象的vector。

#include "Sales_data.h"
#include "include.h"

bool compareIsbn(const Sales_data &a, const Sales_data &b)
{
    return a.isbn() < b.isbn();
}

int main(int argc, char const *argv[])
{
    Sales_data a("999");
    Sales_data b("456");
    Sales_data c("222");

    vector<Sales_data> v = {a, b, c};
    sort(v.begin(), v.end(), compareIsbn);
    for (auto ch : v)
    {
        cout << ch.isbn() << endl;
    }

    while (1)
        ;
    return 0;
}

10.13


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

bool bigThen5(const string &a)
{
    return a.size() > 5;
}

int main(int argc, char const *argv[])
{
    vector<string> v = {"123456",
                        "12345",
                        "111222",
                        "55555555"};

    auto last_true = partition(v.begin(), v.end(), bigThen5);

    for (auto i = v.begin(); i != last_true; i++)
    {
        cout << *i << endl;
    }

    while (1)
        ;
    return 0;
}

10.14

/*
lamdda 接收两个int 返回sum
*/

#include "include.h"
int main(int argc, char const *argv[])
{

    auto f = [](const int a, const int b) { return a + b; };

    cout << f(1, 2) << endl;

    while (1)
        ;
    return 0;
}

10.15

/*
编写一个lambda,捕获它所在函数的int,并接受一个int参数。lambda应该返回捕获的int和int参数的和
*/
#include "include.h"

int main(int argc, char const *argv[])
{
    int a = 1;
    auto f = [a](int b) { return a + b; };
    cout << f(3) << endl;
    while (1)
        ;
    return 0;
}

10.16

/*
求一个大于等于给定长度的单词有多少,并将其打印出来
void biggiest(vector<string>v,vector<string>::size_type sz)
*/
#include "include.h"

void biggiest(vector<string> v, vector<string>::size_type sz)
{
    // 按照字典排序,删除重复单词
    sort(v.begin(), v.end());
    auto last = unique(v.begin(), v.end());
    v.erase(last, v.end());

    // 按照长度排序,这里需要传递一个长度 使用lamada
    stable_sort(v.begin(), v.end(), [](const string &a, const string &b) { return a.size() < b.size(); });

    //找到第一个长度>sz的迭代器
    auto fst = find_if(v.begin(), v.end(), [sz](const string &a) { return a.size() >= sz; });

    // 打印vec
    for_each(fst, v.end(), [](const string &a) { cout << a << endl; });
}

int main(int argc, char const *argv[])
{
    vector<string> v = {"0", "123", "1234", "hello", "world", "99999999999", "world"};
    biggiest(v, 4);

    while (1)
        ;
    return 0;
}

10.17

//重新10.12的程序,在对sort的调用中使用lambda来代替函数compareIsbn

#include "Sales_data.h"
#include "include.h"

bool compareIsbn(const Sales_data &a, const Sales_data &b)
{
    return a.isbn() < b.isbn();
}

int main(int argc, char const *argv[])
{
    Sales_data a("999");
    Sales_data b("456");
    Sales_data c("222");

    vector<Sales_data> v = {a, b, c};
    vector<Sales_data> v2(v);
    sort(v.begin(), v.end(), compareIsbn);

    for (auto ch : v)
    {
        cout << ch.isbn() << endl;
    }

    sort(v2.begin(), v2.end(), [](const Sales_data &a, const Sales_data &b) { return a.isbn() < b.isbn(); });
    for (auto ch : v2)
    {
        cout << ch.isbn() << endl;
    }

    while (1)
        ;
    return 0;
}

10.18

10.19

/*
求一个大于等于给定长度的单词有多少,并将其打印出来
void biggiest(vector<string>v,vector<string>::size_type sz)


-------------------------------sort by dic
0,123,1234,99999999999,hello,world,
-------------------------------sort by dic,then stable_sort by len,then use findif
1234,hello,world,99999999999,
-------------------------------sort by dic,then partition
world,hello,1234,99999999999,
-------------------------------sort by dic,then stable_partition
1234,99999999999,hello,world,


*/
#include "include.h"

string make_plural(size_t ctr, const string &word, const string &ending)
{
    return (ctr > 1) ? word + ending : word;
}
void elimdups(vector<string> &words)
{
    sort(words.begin(), words.end());
    auto end_unique = unique(words.begin(), words.end());
    words.erase(end_unique, words.end());
}

void biggiest2(vector<string> &words, vector<string>::size_type sz)
{
    elimdups(words); //将words按字典序排序,删除重复词

    // 获取一个迭代器,指向最后一个满足size()>=sz的元素之后的位置
    auto wc = partition(words.begin(), words.end(), [sz](const string &a) { return a.size() >= sz; });
    // 计算满足size()>=sz的元素的数目
    auto count = wc - words.begin();
    cout << count << " " << make_plural(count, "word", "s") << " of length " << sz << " or longer" << endl;
    // 打印长度大于等于给定值的单词,每个单词后面接一个空格
    for_each(words.begin(), wc, [](const string &s) { cout << s << " "; });
    cout << endl;
}

void biggiest(vector<string> v, vector<string>::size_type sz)
{
    // 按照字典排序,删除重复单词
    sort(v.begin(), v.end());
    auto last = unique(v.begin(), v.end());
    v.erase(last, v.end());

    vector<string> cp1(v);
    vector<string> cp2(v);

    cout << "-------------------------------sort by dic" << endl;
    for_each(cp1.begin(), cp1.end(), [](const string &a) { cout << a << ","; });
    cout << endl;

    cout << "-------------------------------sort by dic,then stable_sort by len,then use findif" << endl;
    // 按照长度排序,这里需要传递一个长度 使用lamada
    stable_sort(v.begin(), v.end(), [](const string &a, const string &b) { return a.size() < b.size(); });
    //找到第一个长度>sz的迭代器
    auto fst = find_if(v.begin(), v.end(), [sz](const string &a) { return a.size() >= sz; });
    // 打印vec
    for_each(fst, v.end(), [](const string &a) { cout << a << ","; });
    cout << endl;

    cout << "-------------------------------sort by dic,then partition" << endl;
    auto lst = partition(cp1.begin(), cp1.end(), [sz](const string &a) { return a.size() >= sz; });
    for_each(cp1.begin(), lst, [](const string &a) { cout << a << ","; });
    cout << endl;

    cout << "-------------------------------sort by dic,then stable_partition" << endl;
    auto lst2 = stable_partition(cp2.begin(), cp2.end(), [sz](const string &a) { return a.size() >= sz; });
    for_each(cp2.begin(), lst2, [](const string &a) { cout << a << ","; });
    cout << endl;
}

int main(int argc, char const *argv[])
{
    vector<string> v = {"0", "123", "1234", "hello", "world", "99999999999", "world"};
    biggiest(v, 4);

    while (1)
        ;
    return 0;
}

10.20

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

int main(int argc, char const *argv[])
{
    vector<string> v = {"123", "1233", "ssss", "123456789", "123564789"};

    auto cnt = count_if(v.begin(), v.end(), [](const string &a) { return a.size() > 6; });
    cout << cnt << endl;
    while (1)
        ;
    return 0;
}

10.21

/*
编写一个lambda,捕获一个局部int变量,并递减变量值,直至它变为0.一旦变为0,再调用lambda应该不再递减变量。lambda应该返回一个bool值,指出捕获的变量是否为0.
*/
#include "include.h"

int main(int argc, char const *argv[])
{
    int z = 3;

    //auto f = [&z]() {if(z)z--; return(z?false:true); };
    // 也可以使用尾置返回
    auto f = [&z]() -> int {if(z)z--; return(z?false:true); };

    while (z)
    {
        f();
        cout << z << endl;
    }
    while (1)
        ;
    return 0;
}

10.22

/*
重写统计长度小于等于6的单词数量的程序,使用函数代替lambda.
*/
#include "include.h"
#include <functional>
using namespace std::placeholders;
bool cnt(const string &a, string::size_type sz)
{
    return a.size() <= sz;
}

int main(int argc, char const *argv[])
{

    vector<string> v = {"123", "1233", "ssss", "123456789", "123564789"};

    //auto f = bind(cnt, _1, 6);
    //auto cnt = count_if(v.begin(), v.end(), f);

    auto cnt = count_if(v.begin(), v.end(), bind(cnt, _1, 6));
    cout << cnt << endl;
    while (1)
        ;
    return 0;
    while (1)
        ;
    return 0;
}

10.23

bind接受几个参数
第一个参数是函数,后面的参数实际就是函数的参数,

10.24

#include "include.h"

bool check(int a, int sz)
{
    return a > sz;
}

int main(int argc, char const *argv[])
{
    vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    string s = "123";
    auto f = bind(check, _1, s.size());

    auto fst = find_if(v.begin(), v.end(), f);

    cout << *fst << endl;

    while (1)
        ;
    return 0;
}

10.25

/*
求一个大于等于给定长度的单词有多少,并将其打印出来
void biggiest(vector<string>v,vector<string>::size_type sz)

在10.3.2节的练习中,编写了一个使用 partition 的biggies版本.使用check_size和bind重写此函数
    //----------这里是本章答案
    auto f1 = bind(check, _1, sz);
    cout << "-------------------------------sort by dic,then bind" << endl;
    auto lstbind = partition(cp3.begin(), cp3.end(), f1);
    for_each(cp3.begin(), lstbind, [](const string &a) { cout << a << ","; });
    cout << endl;

-------------------------------sort by dic
0,123,1234,99999999999,hello,world,
-------------------------------sort by dic,then stable_sort by len,then use findif
1234,hello,world,99999999999,
-------------------------------sort by dic,then partition
world,hello,1234,99999999999,
-------------------------------sort by dic,then stable_partition
1234,99999999999,hello,world,


*/
#include "include.h"

string make_plural(size_t ctr, const string &word, const string &ending)
{
    return (ctr > 1) ? word + ending : word;
}
void elimdups(vector<string> &words)
{
    sort(words.begin(), words.end());
    auto end_unique = unique(words.begin(), words.end());
    words.erase(end_unique, words.end());
}

void biggiest2(vector<string> &words, vector<string>::size_type sz)
{
    elimdups(words); //将words按字典序排序,删除重复词

    // 获取一个迭代器,指向最后一个满足size()>=sz的元素之后的位置
    auto wc = partition(words.begin(), words.end(), [sz](const string &a) { return a.size() >= sz; });
    // 计算满足size()>=sz的元素的数目
    auto count = wc - words.begin();
    cout << count << " " << make_plural(count, "word", "s") << " of length " << sz << " or longer" << endl;
    // 打印长度大于等于给定值的单词,每个单词后面接一个空格
    for_each(words.begin(), wc, [](const string &s) { cout << s << " "; });
    cout << endl;
}

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

void biggiest(vector<string> v, vector<string>::size_type sz)
{
    // 按照字典排序,删除重复单词
    sort(v.begin(), v.end());
    auto last = unique(v.begin(), v.end());
    v.erase(last, v.end());

    vector<string> cp1(v);
    vector<string> cp2(v);
    vector<string> cp3(v);

    cout << "-------------------------------sort by dic" << endl;
    for_each(cp1.begin(), cp1.end(), [](const string &a) { cout << a << ","; });
    cout << endl;

    cout << "-------------------------------sort by dic,then stable_sort by len,then use findif" << endl;
    // 按照长度排序,这里需要传递一个长度 使用lamada
    stable_sort(v.begin(), v.end(), [](const string &a, const string &b) { return a.size() < b.size(); });
    //找到第一个长度>sz的迭代器
    auto fst = find_if(v.begin(), v.end(), [sz](const string &a) { return a.size() >= sz; });
    // 打印vec
    for_each(fst, v.end(), [](const string &a) { cout << a << ","; });
    cout << endl;

    //------------------------------------------------------------------------------------------------------------这里是本章答案
    auto f1 = bind(check, _1, sz);
    cout << "-------------------------------sort by dic,then bind" << endl;
    auto lstbind = partition(cp3.begin(), cp3.end(), f1);
    for_each(cp3.begin(), lstbind, [](const string &a) { cout << a << ","; });
    cout << endl;

    cout << "-------------------------------sort by dic,then partition" << endl;
    auto lst = partition(cp1.begin(), cp1.end(), [sz](const string &a) { return a.size() >= sz; });
    for_each(cp1.begin(), lst, [](const string &a) { cout << a << ","; });
    cout << endl;

    cout << "-------------------------------sort by dic,then stable_partition" << endl;
    auto lst2 = stable_partition(cp2.begin(), cp2.end(), [sz](const string &a) { return a.size() >= sz; });
    for_each(cp2.begin(), lst2, [](const string &a) { cout << a << ","; });
    cout << endl;
}

int main(int argc, char const *argv[])
{
    vector<string> v = {"0", "123", "1234", "hello", "world", "99999999999", "world"};
    biggiest(v, 4);

    while (1)
        ;
    return 0;
}

10.26

解释三种插入迭代器的不同之处

back_inserter 总是执行push_back  尾部插入
front_inserter 执行 push_front  头部插入
inserter(container,where)  在where前插入后,返回where 也就是原来的迭代器的位置

10.27

/*
除了unique之外,标准库还定义了名为unique_copy的函数,
它接受第三个迭代器,表示拷贝不重复元素的目的位置。
编写一个程序,使用unique_copy将一个vector中不重复的元素拷贝到一个初始为空的list中
*/

#include "include.h"

int main(int argc, char const *argv[])
{

    vector<int> v = {1, 2, 3, 4, 5, 2, 3, 1, 4, 1, 2, 3, 4, 5, 9};
    list<int> l;

    sort(v.begin(), v.end());

    auto last = unique_copy(v.begin(), v.end(), back_inserter(l));

    for_each(l.begin(), l.end(), [](const int &i) { cout << i << " "; });
    cout << endl;

    while (1)
        ;
    return 0;
}

10.28

/*
一个vector中保存1到9共9个值,将其拷贝到三个其他容器中。分别使用inserter、back_inserter 和front_inserter将元素添加到三个容器中。
对每种 inserter,估计输出序列是怎样的,运行程序验证你的估计是否正确  
*/

#include "include.h"

int main(int argc, char const *argv[])
{
    vector<int> v;
    list<int> v1;
    list<int> v2;
    list<int> v3;

    for (int i = 0; i < 9; i++)
        v.push_back(i);

    copy(v.begin(), v.end(), inserter(v1, v1.begin())); // 0,1,2,3,4,5,6,7,8,
    copy(v.begin(), v.end(), back_inserter(v2));        // 0,1,2,3,4,5,6,7,8,
    copy(v.begin(), v.end(), front_inserter(v3));       // 8,7,6,5,4,3,2,1,0,

    for_each(v1.begin(), v1.end(), [](const int ch) { cout << ch << ","; });
    cout << endl;
    for_each(v2.begin(), v2.end(), [](const int ch) { cout << ch << ","; });
    cout << endl;
    for_each(v3.begin(), v3.end(), [](const int ch) { cout << ch << ","; });
    cout << endl;

    while (1)
        ;
    return 0;
}

10.29

/*
编写程序,使用流迭代器读取一个文本文件,存入一个vector中的string里
 1:  vector<string> v(in_iter, eof_f);
 2: copy(in_iter, eof_f, back_inserter(vec));

*/
#include <fstream>
#include <iterator>

#include "include.h"

int main(int argc, char const *argv[])
{

    ifstream in_f("E:\\Reading\\C++\\C+++Primer\\CppPrimer-master\\CppPrimer\\10th\\10.29.cpp");
    istream_iterator<string> in_iter(in_f);
    istream_iterator<string> eof_f;

    // 方式1
    vector<string> v(in_iter, eof_f);
    for_each(v.begin(), v.end(), [](const string &ch) { cout << ch << endl; });

    //方式2
    vector<string> vec;
    copy(in_iter, eof_f, back_inserter(vec));
    std::copy(v.cbegin(), v.cend(), std::ostream_iterator<string>(std::cout, "\n"));

    while (1)
        ;
    return 0;
}

10.30

/*使用流迭代器、sort和copy从标准输入读取一个整数序列,将其排序,并将结果写到标准输出
*/
#include "include.h"
#include <iterator>

int main(int argc, char const *argv[])
{
    istream_iterator<int> in(cin), eof;
    ostream_iterator<int> out(cout, ",");
    vector<int> v(in, eof);
    sort(v.begin(), v.end());
    copy(v.begin(), v.end(), out);

    while (1)
        ;
    return 0;
}

10.31

/*
修改前一题的程序,使其只打印不重复的元素。你的程序应使用unique_copy
*/

#include "include.h"
#include <iterator>

int main(int argc, char const *argv[])
{
    istream_iterator<int> in(cin), eof;
    ostream_iterator<int> out(cout, ",");
    vector<int> v(in, eof);
    sort(v.begin(), v.end());
    //_copy(v.begin(), v.end(), out);
    unique_copy(v.begin(), v.end(), out);

    while (1)
        ;
    return 0;
}

10.32

/*
10.32 重写1.6节的书店程序,使用一个vector保存交易记录,使用不同算法完成处理。使用sort和10.3.1节中的compareIsbn函数来排序交易记录,然后使用find和accumulate求和。
*/

#include "include.h"
#include "../include/Sales_item.h"
#include <numeric>
#include <iterator>

void TestNew()
{
    cout << "Usage input: name_id[string] ,count[unsigned] , value[doubel]" << endl;
    istream_iterator<Sales_item> in(cin), eof;
    vector<Sales_item> v(in, eof);
    sort(v.begin(), v.end(), compareIsbn);
    for (auto beg = v.cbegin(), end = beg; beg != v.cend(); beg = end)
    {
        end = find_if(beg, v.cend(), [beg](const Sales_item &nextv) { return nextv.isbn() != beg->isbn(); });
        cout << accumulate(beg, end, Sales_item(beg->isbn())) << endl;
    }

    // std::istream_iterator<Sales_item> in_iter(std::cin), in_eof;
    // std::vector<Sales_item> vec;

    // while (in_iter != in_eof)
    //     vec.push_back(*in_iter++);
    // sort(vec.begin(), vec.end(), compareIsbn);
    // for (auto beg = vec.cbegin(), end = beg; beg != vec.cend(); beg = end)
    // {
    //     end = find_if(beg, vec.cend(), [beg](const Sales_item &item) { return item.isbn() != beg->isbn(); });
    //     std::cout << std::accumulate(beg, end, Sales_item(beg->isbn())) << std::endl;
    // }
}

int TestOld(void)
{
    cout << "Usage input: name_id[string] ,count[unsigned] , value[doubel]" << endl;
    Sales_item last;

    if (cin >> last)
    {
        Sales_item now;
        while (cin >> now)
        {
            if (now.isbn() == last.isbn())
            {
                last += now;
            }
            else
            {
                cout << last << endl;
                last = now;
            }
        }
        cout << now << endl;
    }
    else
    {
        cout << "input err " << endl;
        return -1;
    }
    return 0;
}
int main(int argc, char const *argv[])
{
    //TestOld();
    TestNew();
    while (1)
        ;
    return 0;
}

10.33

/*
编写程序,接受三个参数:一个输入文件和两个输出文件的文件名。输入文件保存的应该是整数。
使用istream_iterator读取输入文件。使用ostream_iterator将奇数写入第一个输出文件,每个值之后都跟一个空格。
将偶数写入第二个输出文件,每个值都独占一行
*/

#include "include.h"
#include <fstream>
#include <iterator>

int main(int argc, char const *argv[])
{
    const char *path = "D:\\0.txt";
    const char *path1 = "D:\\1.txt";
    const char *path2 = "D:\\2.txt";

    ifstream fin(path);
    ofstream fout1(path1);
    ofstream fout2(path2);

    if (!fin)
        cout << "open" << path << "faile" << endl;
    if (!fout1)
        cout << "open" << path1 << "faile" << endl;
    if (!fout2)
        cout << "open" << path2 << "faile" << endl;
    if (!fin || !fin || !fout2)
        while (1)
            ;

    istream_iterator<int> in(fin), iof;
    ostream_iterator<int> o1(fout1, " ");
    ostream_iterator<int> o2(fout2, "\n");

    while (in != iof)
    {

        cout << *in << endl;
        if (*in & 0x01)
        {
            *o1++ = *in;
        }
        else
        {
            *o2++ = *in;
        }
        in++;
    }

    fout1.close();
    fout2.close();
    while (1)
        ;
    return 0;
}

10.34

10.35

/*
1. 反向迭代器 逆序输出vector
2. 普通迭代器 逆序输出
*/
#include "include.h"
#include <iterator>
int main(int argc, char const *argv[])
{
    vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9};

    copy(v.crbegin(), v.crend(), ostream_iterator<int>(cout, ","));
    cout << endl;

    //copy(v.crbegin(), v.crend(), ostream_iterator<int>(cout, ","));
    auto beg1 = v.end() - 1;
    for (; beg1 != v.begin(); advance(beg1, -1))
    {
        cout << *beg1 << ",";
    }
    cout << *beg1 << endl;

    

    while (1)
        ;
    return 0;
}

10.36

10.37

/*使用find在一个int的list中查找最后一个值为0的元素。*/
/*给定一个包含10个元素的vector,将位置3到7之间的元素按逆序拷贝到一个list中*/

#include "include.h"
int main(int argc, char const *argv[])
{
    list<int> l = {1, 2, 3, 5, 0, 1, 2, 5, 8, 2, 0, 3, 15};

    auto last_zero_it = find(l.crbegin(), l.crend(), 0);
    cout << distance(last_zero_it, l.crend()) << endl;
    for_each(l.cbegin(), last_zero_it.base(), [](const int c) { cout << c << ","; });
    cout << endl;

    //////////end   -1  -2
    vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    list<int> l2(v.rend() - 7, v.rend() - 2);
    for_each(l2.cbegin(), l2.cend(), [](const int c) { cout << c << ","; });

    //// 另一种方式,但是他这种对于vector不友好,一直在头部插入,对于list无所谓
    ////copy(vec.cbegin() + 3, vec.cbegin() + 8, ret_lst.rbegin());

    while (1)
        ;
    return 0;
}

10.38

5个迭代器的类别:
迭代器 简述
输入 只读 解引用在=右侧,用一次,迭代器支持!=,==,++,->
输出 只写 解引用在=左侧,用一次,迭代器支持++
前向 只能递增 可以多次读写同一个位置
双向 能加能减
随机 +-具体数字 可以使用下标

10.39

10.40

list 双向迭代
vec   随机迭代器

cop      输入迭代器,输出迭代器
reverse  需要将范围内的元素反向处理,>>>双向迭代器
unique	 去除相邻的重复元素,也就是逐一扫描->>>前向

10.41

/*仅根据算法和参数的名字,描述下面每个标准库算法执行什么操作*/
replace(beg, end, old_val, new_val);					1.替换范围内的old_val元素为 new_val
replace_if(beg, end, pred, new_val);					2.元素满足pred的条件,替换为new_val
replace_copy(beg, end, dest, old_val, new_val);			3. 使用copy而非直接替换
replace_copy_if(beg, end, dest, pred, new_val);			4. 使用copy而非直接替换

10.42

/*
使用list代替vector重新实现10.2.3节中的去除重复单词的程序
*/

#include "include.h"

int main(int argc, char const *argv[])
{
    list<string> l = {"1",
                      "my",
                      "2",
                      "3",
                      "2",
                      "heel",
                      "my"};
    l.sort();
    l.unique();
    for_each(l.begin(), l.end(), [](const string &c) { cout << c << endl; });
    while (1)
        ;
    return 0;
}

推荐阅读