zoukankan      html  css  js  c++  java
  • cppPrimer学习-9th


    title: cppPrimer学习9th date: 2020/1/3 10:37:05 toc: true

    cppPrimer学习9th

    [TOC]

    源代码

    https://github.com/Layty/CppPrimer

    知识点

    我的小模版

    #include <forward_list>
    #include <iostream>
    #include <list>
    #include <vector>
    using namespace std;
    
    template <typename T> 
    void print(T src)
    {
        for (auto ch : src) 
            cout << ch <<",";
        cout<<endl;
    }
    
    int main(int argc, const char** argv)
    {
    
    	while(1);
    }
    
    • resize改变的是size,reserve表示的是容量的预分配

    • 在string转数字的时候,使用if(ch.find_first_of("0123456789")!=string::npos)后再来处理数字避免异常等,可以看练习题9.50.转换数字的字符串第一个字符要是合法的+-.0123456789

    • string用char来构造,string(1,ch)

    练习题

    9.1

    9.1 对于下面的程序任务,vector, deque和list哪种容器最为合适?解释你选择的理由。如果没有哪一种容器优于其它容器,也请解释理由。
    
    读取固定数量的单词,将它们按字典序插入到容器中。我们将在下一章看到,关联容器更适合这个问题。
    读取未知数量的单词,总是将新单词插入到末尾。删除操作在头部进行。
    从一个文件中读取未知数量的整数。将这些整数排序,然后打印到标准输出。
    
    1. 别人的答案使用list,因为涉及到中间插入,但是按照书本的解释,我觉得可以先使用vector存放,再使用sort排序,这里作者有写固定数量

      mark

    2. 使用deque

    3. 因为整数是小容量大小的数据元素,这里使用vector,再使用sort

    9.2

    定义一个list对象,其元素类型是int的deque。
    
    list< deque<int> >
    

    9.3

    构成迭代器范围的迭代器有何限制
    
    [begin,end)
    begin++ 能够到达end
    

    9.4

    /**
     * 编写一个函数,接受一对指向vector的迭代器和一个int值。在两个迭代器指定的范围中查找给定的值,返回一个布尔值来指出是否找到
     */
    
    #include <iostream>
    #include <vector>
    using namespace std;
    
    bool findInt(vector<int>::iterator src_begin, vector<int>::iterator src_end, int num)
    {
    
        for (vector<int>::iterator i = src_begin; i != src_end; i++) {
            if (*i == num) return true;
        }
        return false;
    }
    
    int main(int argc, const char** argv)
    {
        vector<int> a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
    
        for (auto ch : a) {
            cout << ch << ",";
        }
        cout << endl;
    
        bool find = findInt(a.begin(), a.end(), 155);
        cout << "find 155 is " << boolalpha << find << endl;
        find = findInt(a.begin(), a.end(), 1);
        cout << "find 1 is " << boolalpha << find << endl;
    
        while (1) {
            ;
        }
    
        return 0;
    }
    
    
    

    9.5

    /**
     *重写上一题的函数,返回一个迭代器指向找到的元素。注意,程序必须处理未找到给定值的情况
     */
    
    #include <iostream>
    #include <vector>
    using namespace std;
    
    vector<int>::iterator findInt(vector<int>::iterator src_begin, vector<int>::iterator src_end, int num)
    {
    
        for (vector<int>::iterator i = src_begin; i != src_end; i++) {
            if (*i == num) return i;
        }
        return src_end;
    }
    
    int main(int argc, const char** argv)
    {
        vector<int> a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
    
        for (auto ch : a) {
            cout << ch << ",";
        }
        cout << endl;
    
        auto find = findInt(a.begin(), a.end(), 155);
        if (find == a.end()) {
            cout << "no number find" << endl;
        }
        find = findInt(a.begin(), a.end(), 1);
        if (find != a.end()) {
            cout << "find 1 is " << *find << endl;
        }
        while (1) {
            ;
        }
    
        return 0;
    }
    

    9.6

    下面程序有何错误?你应该如何修改?
    
    list<int> lstl;
    list<int>::iterator iter1 = lstl.begin(),
                       iter2 = lstl.end();
    while (iter1 < iter2)   /* ... */
    
    
    迭代器是指针,对于指针比较大小没有什么意义,如果是 vector 或者 array 或者 deque 的话内存连续可以用作遍历
    但是list 的地址不是连续的
    

    9.7

     为了索引int的vector中的元素,应该使用什么类型?
     
     vector<int> sizetype    索引也就是下标
     
     #include <iostream>
    #include <vector>
    using namespace std;
    
    int main(int argc, const char** argv)
    {
    
        vector<int> a = {1, 2, 3, 4, 5, 6, 7, 8};
        cout << a.size() << endl; // 8
        while (1)
            ;
        return 0;
    }
    

    9.8

    为了读取string的list的元素,应该使用什么类型?如果写入list,又该使用什么类型
    
    写: list<string>::iterator 
    读: list<string>::const_iterator    
    

    9.9

    begin和cbegin两个函数有什么不同
    
    iterator 和 const_iterator
    

    9.10

    /* 下面的4个对象分别是什么类型 */ 
    vector<int> v1;
    const vector<int> v2;
    auto it1 = v1.begin(), it2 = v2.begin();
    auto it3 = v1.cbegin(), it4 = v2.cbegin();
    
    it1 vector<int>::iterator
    it2 vector<int>::const_iterator
    it3 vector<int>::const_iterator
    it4 vector<int>::const_iterator
    

    9.11

    /*
    对6种创建和初始化vector对象的方法,每一种都给出一个实例。解释每个vector包含什么值
    */
    
    #include <iostream>
    #include <vector>
    using namespace std;
    
    void printVecInfo(const vector<int> src)
    {
        cout << "size=" << src.size() << "   :    ";
        for (auto ch : src) cout << ch << ",";
        cout << endl;
    }
    
    int main(int argc, const char** argv)
    {
        using C = vector<int>;
    
        C a1;
        C a2{1, 2, 3, 4, 5, 6, 7, 8, 9};
        C a3 = a2;
        C a4(a2.begin(), a2.begin() + 2);
        C a5(5);
        C a6(6, 1);
    
        printVecInfo(a1); // size=0   :
        printVecInfo(a2); // size=9   :    1,2,3,4,5,6,7,8,9,
        printVecInfo(a3); // size=9   :    1,2,3,4,5,6,7,8,9,
        printVecInfo(a4); // size=2   :    1,2,
        printVecInfo(a5); // size=5   :    0,0,0,0,0,
        printVecInfo(a6); // size=6   :    1,1,1,1,1,1,
    
        while (1) {
            ;
        }
    
        return 0;
    }
    

    9.12

     对于接受一个容器创建其拷贝的构造函数,和接受两个迭代器创建拷贝的构造函数,解释它们的不同
     
     答案在p300顶部
     接受一个容器创建其拷贝的构造函数,要求两个容器类型及元素类型必须匹配。
     接受两个迭代器创建拷贝的构造函数,不要求容器类型匹配,而且元素类型也可以不同,只要拷贝的元素能转换就可以
     
    list<int> numbers = {1, 2, 3, 4, 5};
    list<int> numbers2(numbers);        // ok, numbers2 has the same elements as numbers
    vector<int> numbers3(numbers);      // error: no matching function for call...
    list<double> numbers4(numbers);     // error: no matching function for call...
    
    
    list<int> numbers = {1, 2, 3, 4, 5};
    list<int> numbers2(numbers.begin(), numbers.end);        // ok, numbers2 has the same elements as numbers
    vector<int> numbers3(numbers.begin(), --numbers.end());  // ok, numbers3 is {1, 2, 3, 4}
    list<double> numbers4(++numbers.beg(), --numbers.end());        // ok, numbers4 is {2, 3, 4}
    forward_list<float> numbers5(numbers.begin(), numbers.end());   // ok, number5 is {1, 2, 3, 4, 5}
    
    

    9.13

    /*如何用一个list<int>初始化一个vector<double>, 从一个vector<int>又该如何创建*/
    
    #include <iostream>
    #include <list>
    #include <vector>
    using namespace std;
    
    int main(int argc, const char** argv)
    {
    
        list<int> a = {1, 2, 3, 4, 5, 6, 7};
        vector<double> b(a.begin(), a.end());
        vector<int> c = {1, 2, 3, 4, 5, 6, 7};
        vector<double> d(c.begin(), c.end());
    
        return 0;
    }
    

    9.14

    /*
    编写程序,将一个list中的char*指针(指向C风格字符串)元素赋值给一个vector中的string
    */
    
    #include <iostream>
    #include <list>
    #include <string>
    #include <vector>
    using namespace std;
    
    int main(int argc, const char** argv)
    {
    
        list<const char*> a(10, "hello");
        vector<string> b;
        b.assign(a.begin(), a.end());
        for (auto ch : b) cout << ch << endl;
    
        while (1)
            ;
    }
    

    9.15

    // 编写程序,判定两个vector是否相等。
    #include <iostream>
    #include <vector>
    using namespace std;
    
    int main(int argc, const char** argv)
    {
    
        vector<int> a = {1, 2, 3, 4, 5, 6};
        vector<int> b = {2, 2, 3, 4, 5, 6};
    
        cout << boolalpha << (a == b) << endl;
        while (1)
            ;
    }
    

    9.16

    /*重写上一题的程序,比较一个list中的一个元素和一个vector中的元素。
    先转换list到vector 再比较
    */
    
    
    #include <iostream>
    #include <list>
    #include <vector>
    using namespace std;
    
    int main(int argc, const char** argv)
    {
    
        list<int> a(5, 1);
        vector<int> b(6, 1);
    
        cout << boolalpha << (vector<int>(a.begin(), a.end()) == b) << endl;
        while (1)
            ;
        return 0;
    }
    

    9.17

    假定c1和c2是两个容器,下面的比较操作有何限制
    容器类型相同
    容器元素类型相同
    容器的元素支持比较运算 包括=,<
    

    9.18

    /*
    编写程序,从标准输入读取string序列,存入一个deque中。编写一个循环,用迭代器打印deque中的元素
    备注: 这里需要使用ctrl+z
    */
    
    #include <deque>
    #include <string>
    #include <vector>
    
    #include <iostream>
    using namespace std;
    
    int main(int argc, const char** argv)
    {
    
        string tmp;
        deque<string> put;
        while (cin >> tmp) {
            put.push_back(tmp);
        }
        cout << "you input :
    ";
    
        for (auto ch = put.begin(); ch != put.end(); ch++) {
            cout << *ch << endl;
        }
    
        while (1) {
            /* code */
        }
    
        return 0;
    }
    

    9.19

    重写上题程序,用list代替deque。列出程序要做出哪些改变。
    将deque改为list类型 iterator的类型也改为list即可。
    

    9.20

    /*
    从一个list拷贝元素到两个deque中。值为偶数的所有元素都拷贝到一个deque中,而奇数值元素都拷贝到另一个deque中
    */
    #include <deque>
    #include <iostream>
    #include <list>
    #include <string>
    #include <vector>
    using std::cin;
    using std::cout;
    using std::deque;
    using std::endl;
    using std::list;
    using std::string;
    using std::vector;
    // 大佬的代码
    // int main()
    // {
    //     list<int> l{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    //     deque<int> odd, even;
    //     for (auto i : l) (i & 0x1 ? odd : even).push_back(i);
    
    //     for (auto i : odd) cout << i << " ";
    //     cout << endl;
    //     for (auto i : even) cout << i << " ";
    //     cout << endl;
    
    //     return 0;
    // }
    
    int main()
    {
        list<int> src;
        deque<int> dst1;
        deque<int> dst2;
    
        int num;
        while (cin >> num) src.push_back(num);
        for (int num : src) {
            if (num & 0x01)
                dst1.push_back(num);
            else
                dst2.push_back(num);
        }
    
        cout << "one" << endl;
        for (int num : dst1) {
            cout << num << " ";
        }
        cout << endl;
        cout << "two" << endl;
        for (int num : dst2) cout << num << " ";
    
        cout << endl;
        while (1)
            ;
        return 0;
    }
    

    9.21

    /* 如果我们将308页中使用insert返回值将元素添加到list中的循环程序改写为将元素插入到vector中,分析循环将如何工作
    
        list<string> lst;
        auto iter =lst.begin();
        while(cin>>word)
            iter=lst.insert(iter,word)
    */
    一直往头部插入,vector 会执行拷贝移动
    

    9.22

    /*
    假定iv是一个int的vector,下面的程序存在什么错误?你将如何修改?
    
    vector<int>::iterator iter = iv.begin(), mid = iv.begin() + iv.size()/2;
    
    while(iter != mid) {
        if (*iter == some_val) {
            iv.insert(iter, 2 * some_val);
        }
    }
    
    1. iter 是iv 的迭代器,插入后长度变了,mid也就失效了 同时当vector扩大时,地址全部失效了
    2. 死循环,iter没有++
    
    insertDoubleValue2 是我写的,,这里取巧了,因为end是一直变的,我们根据end-cursor就好了
    */
    
    #include <iostream>
    #include <vector>
    using std::vector;
    
    void insertDoubleValue(vector<int>& iv, int some_val)
    {
        auto cursor = iv.size() / 2;
        auto iter = iv.begin(), mid = iv.begin() + cursor;
        while (iter != mid) {
            if (*iter == some_val) {
                iter = iv.insert(iter, 2 * some_val);
                ++iter;
                ++cursor;
                mid = iv.begin() + cursor;
            }
            ++iter;
        }
    }
    
    void insertDoubleValue2(vector<int>& iv, int some_val)
    {
        auto cursor = iv.size() / 2;
        auto iter = iv.begin();
        while (iter != iv.end() - cursor) {
            if (*iter == some_val) {
                iter = iv.insert(iter, 2 * some_val);
                ++iter;
            }
            ++iter;
        }
    }
    
    void print(const vector<int>& iv)
    {
        for (auto i : iv) std::cout << i << " ";
        std::cout << std::endl;
    }
    
    int main()
    {
        vector<int> iv = {1, 1, 1, 1, 1, 7, 1, 9, 8};
        insertDoubleValue(iv, 1);
        print(iv);
    
        iv = {1, 1, 1, 1, 1, 7, 1, 9, 8};
        insertDoubleValue2(iv, 1);
        print(iv);
        while (1)
            ;
    }
    
    

    9.23

    在本节第一个程序(309页)中,若c.size()为1, 则val, val2, val3和val4的值会是什么
        第一个元素
    

    9.24

    编写程序,分别使用at、下标运算符、front和begin提取一个vector中的第一个元素。
        在一个空vector上测试你的程序
        
        
    #include <iostream>
    #include <vector>
    using namespace std;
    
    int main(int argc, const char** argv)
    {
    
        std::vector<int> v;
        std::cout << v.at(0);    // terminating with uncaught exception of type std::out_of_range
        std::cout << v[0];       // Segmentation fault: 11
        std::cout << v.front();  // Segmentation fault: 11
        std::cout << *v.begin(); // Segmentation fault: 11
    
        while (1) return 0;
    }
    

    9.25

    对于312页中删除一个范围内的元素的程序,如果elem1与elem2相等会发生什么?
    
    
    如果elem2是尾后迭代器,或者elem1和elem2皆为尾后迭代器,又会发生什么
    elem1=slist.erase(elements,elem2)
    
    1. 不删除元素,不发生改变
    2. 清空元素
    3. 不删元素,不发生改变
    

    9.26

    /*
    使用下面代码定义的ia,将ia拷贝到一个从vector和一个list中。
    使用单迭代器版本的erase从list中删除奇数元素,从vector中删除偶数元素。
    */
    #include <iostream>
    #include <list>
    #include <vector>
    using namespace std;
    
    int main(int argc, const char** argv)
    {
        int ia[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89};
    
        // 这么做也可以,说明迭代器是+1的计算方式
        // vector<int> va(ia, ia + sizeof(ia) / sizeof(int));
        vector<int> va(begin(ia), end(ia));
    
        list<int> lb(va.begin(), va.end());
    
        for (auto it = va.begin(); it != va.end();) {
            if ((*it) % 2)
                it = va.erase(it);
            else
                it++;
        }
    
        for (auto it = lb.begin(); it != lb.end();) {
            if ((*it) % 2)
                it++;
            else
                it = lb.erase(it);
        }
    
        for (auto ch : va) cout << ch << ",";
        cout << endl;
        for (auto ch : lb) cout << ch << ",";
        cout << endl;
    
        while (1)
            ;
        return 0;
    }
    

    9.27

    /*
    编写程序,查找并删除forward_list中的奇数元素。
    */
    #include <forward_list>
    #include <iostream>
    using namespace std;
    int main(int argc, const char** argv)
    {
    
        forward_list<int> flst = {2, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    
        auto prev = flst.before_begin();
        auto curr = flst.begin();
    
        while (curr != flst.end()) {
            if (*curr % 2) {
                curr = flst.erase_after(prev);
            }
            else {
                prev = curr;
                curr++;
            }
        }
    
        for (auto ch : flst) cout << ch << ",";
    
        while (1)
            ;
        return 0;
    }
    

    9.28

    /*
    编写函数,接受一个forward_list和两个string共三个参数。
    函数应在链表中查找第一个string,并将第二个string插入到紧接着第一个string之后的位置。
    若第一个string未在链表中,则将第二个string插入到链表末尾。
    */
    
    #include <forward_list>
    #include <iostream>
    #include <string>
    using namespace std;
    
    void insert_lst(forward_list<string>& src, string after, string what)
    {
        if (src.empty()) {
            return;
        }
    
        auto prev = src.before_begin();
        auto curr = src.begin();
    
        while (curr != src.end()) {
            if (*curr == after) {
                src.insert_after(curr, what);
                return;
            }
            else {
                curr++;
                prev++;
            }
        }
        src.insert_after(prev, what);
    }
    
    int main(int argc, const char** argv)
    {
    
        forward_list<string> lst = {"www", ".baidu", ".com"};
    
        insert_lst(lst, ".baidu", ".hello");
        for (auto ch : lst) cout << ch << endl;
        insert_lst(lst, "xxx", ".hello");
        for (auto ch : lst) cout << ch << endl;
        while (1)
            ;
        return 0;
    }
    

    9.29

    假定vec包含25个元素,那么vec.resize(100)会做什么?如果接下来调用vec.resize(10)会做什么
        1. 尾部添加75个0,同时可能因为移动拷贝,迭代器失效
        2. 丢弃尾巴的90个元素
    

    9.30

    接受单个参数的resize版本对元素类型有什么限制
    
    如果是类的话,需要有默认构造函数,或者初始值
    

    9.31

    // 大佬使用了  advance(prv, 2) 来操作迭代器
    
    /*第316页中删除偶数值元素并复制奇数值元素的程序不能用于list或forward_list。
    修改程序,使之也能用于这些类型
    */
    #include <forward_list>
    #include <iostream>
    #include <list>
    #include <vector>
    using namespace std;
    
    template <typename T> 
    void print(T src)
    {
        for (auto ch : src) 
            cout << ch <<",";
        cout<<endl;
    }
    
    int main(int argc, const char** argv)
    {
        vector<int> v1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        list<int> l1(v1.begin(),v1.end());
        forward_list<int> l2(v1.begin(),v1.end());
    
    
        // 删除偶数元素,复制每个奇数元素
        auto it1 = v1.begin();
        while (it1 != v1.end()) {
            if (*it1 % 2) {
                it1 = v1.insert(it1, *it1);
                it1+=2;
            }
            else {
                it1=v1.erase(it1);
            }
        }
        print(v1);
    
    
        {   // list 使用两个++
            // 删除偶数元素,复制每个奇数元素
            auto it1 = l1.begin();
            while (it1 != l1.end()) {
                if (*it1 % 2) {
                    it1 = l1.insert(it1, *it1);
                    it1++;
                    it1++;
    
                }
                else {
                    it1=l1.erase(it1);
                }
            }
            print(l1);
        }
    
    
        {   // forward_list 只有insert_after
            // 删除偶数元素,复制每个奇数元素
            auto curr = l2.begin();
            auto prev=l2.before_begin();
            while (curr != l2.end()) {
                if (*curr % 2) {
                    prev = l2.insert_after(prev,*curr); 
                    prev++;         // 指向了原来的curr
                    //curr=prev;    // 可以注释掉,这里不会发生迭代器失效
                    curr++;
                }
                else {
                    curr=l2.erase_after(prev);
                }
            }
            print(l2);
        }
    
        while (1);
    
        return 0;
    }
    

    9.32

    
    316页的程序中,向下面语句这样调用insert是否合法?如果不合法,为什么?
    iter = vi.insert(iter, *iter++);
    
    *从右到左
    iter++ 从左到右.++ 操作的是iter
    *iter++ 根据优先级 *iter  然后iter++
    https://stackoverflow.com/questions/2934904/order-of-evaluation-in-c-function-parameters
    
    
    无法确认是先执行  *iter++ 还是先 insert  
    或者返回后 先赋值给iter  还是先iter++,再返回给iter
    

    9.33

    在本节最后一个例子中,如果不将insert的结果赋予begin,将会发生什么?
    编写程序,去掉此赋值语句,验证你的答案。
    
    #include "include.h"
    
    
    int main(int argc, const char** argv) {
     
        vector<int> ivec = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        auto iter = ivec.begin();
        while (iter != ivec.end()) {
            ++ iter;
            /* iter = */ivec.insert(iter, 42);
            // 调试可以发现 刚开始 iter=2
            // 执行玩insert后=0 失效了
            ++ iter;
        }
    
        print(ivec);
    
        while(1);
        return 0;
    

    9.34

    死循环
    
    /*假定vi是一个保存int的容器,其中有偶数值也要奇数值,分析下面循环的行为,然后编写程序验证你的分析是否正确。*/
    
    
    
    #include "include.h"
    
    int main(int argc, const char** argv) {
     
        vector<int> v1={1,2,3,4,5,6,7,8,9};
    
        auto iter=v1.begin();
        while(iter!=v1.end())
        {
            if(*iter%2)
            {
                iter=v1.insert(iter,*iter);
                // ++iter;  ///-----if里面也需要++一次
            }
            ++iter;
        }
        print(v1);
        while(1);
        return 0;
    }
    

    9.35

    解释一个vector的capacity和size有何区别
    capacity 表示不用重新分配内存时占用的内存大小
    size 表示已经存储的元素的大小
    

    9.36

    一个容器的capacity可能小于它的size吗
    不会
    capacity >= size
    

    9.37

    为什么list或array没有capacity成员函数?
    
    list 是链表,插入的时候分配内存
    array 是固定大小的
    

    9.38

    /**
        编写程序,探究在你的标准库实现中,vector是如何增长的
     */
    
    #include "include.h"
    
    
    void printInfo(vector<int> &v)
    {
        cout <<"size="<<v.size()<<endl;
        cout <<"capacity="<<v.capacity()<<endl;
    }
    
    int main(int argc, const char** argv) {
     
        vector<int> v1;
        printInfo(v1);      //size=0,capacity=0
    
        v1.push_back(1);    //size=1,capacity=1
        printInfo(v1);      
    
        v1.push_back(1);    //size=2,capacity=2
        printInfo(v1);
    
        v1.push_back(1);    //size=3,capacity=4
        printInfo(v1);
    
    
        while(1);
        return 0;
    }
    

    9.39

    vector<string> svec;
    svec.reserve(1024);
    string word;
    while (cin >> word) {
        svec.push_back(word);
    }
    svec.resize(svec.size() + svec.size()/2);
    
    1. 分配容量为1024的容器,如果超了的话再分配
    2. 填充后1/4 为空串  最后使用resize只能改变vector的size,不能改变其capacity
    
    

    9.40

    如果上一题的程序读入了256个词,在resize之后容器的capacity可能是多少?
    如果读入了512个、1000个或1048个词呢?
    
    
    256---256+256/2=384-------1024
    512---512+512/2=768-------1024
    1000--1000+1000/2=1500----这个可能是2048,但实际是//size=1500 capacity=2000
    1048--1024*2=1536---------2048吧 
    
    // 可以看出来 直接  resize 出来的 capacity= resize*2-----这里可能编译器做法不一样的
    // 直接push一个个的是+1
        
        
        
    #include "include.h"
    
    template<typename T>
    void printInfo(const T& v)
    {
        cout <<"size="<<v.size()<<endl;
        cout <<"capacity="<<v.capacity()<<endl;
    }
    
    
    int main(int argc, const char** argv) {
    
        vector<string> svec;
        svec.reserve(1024);
        string word;
    
        for(int i=0;i<1000;i++){
            svec.push_back("123");
        }
        svec.resize(svec.size() + svec.size()/2);
        printInfo(svec);//size=1500 capacity=2000----------------------------
    
    
        vector<string> svec2;
        svec2.reserve(1024);
        for(int i=0;i<1500;i++){
            svec2.push_back("123");
        }
        printInfo(svec2);//size=1500 capacity=2048--------------------------
     
        while(1);
        return 0;
    }
    
    

    9.41

    /*
        从vector<char> 创建 string
    */
    #include "include.h"
    
    
    int main(int argc, char const *argv[])
    {
        vector<char> vstr={'1','2','3',''};
    
        string s(vstr.begin(),vstr.end());
        cout<<s<<endl;
        while(1);
        return 0;
    }
    

    9.42

    假定你希望每次读取一个字符存入一个string中,而且知道最少需要读取100个字符,应该如何提高性能
    
    使用reserve提前分配好空间,来确保 capacity 大于100
    

    9.43

    9.44

    /*
    编写一个函数,接受三个string参数s,oldVal和newVal.使用迭代器及insert和erase函数将s中所有oldVal替换为newVal。测试你的程序,用它替换通用的简写形式,如,将“tho”替换为“though”,将“thru”替换为“through”。
    
    replaceString   迭代器
    replaceString0  下标+replace
    */
    
    #include "include.h"
    
    
    
    // 使用了下标,和replace
    void replaceString0(string& s,string& sold, string& snew)
    {
        size_t sold_size=sold.size();
        for(size_t i=0;i+sold_size<s.size();i++)
        {
            if(s.substr(i,sold_size)==sold)
            {
                s.replace(i,sold_size,snew);
                i+=snew.size();
            }
        }
    }
    
    
    // 使用了下标,不符合题目
    void replaceString1(string& s,string& sold, string& snew)
    {
        size_t sold_size=sold.size();
        for(size_t i=0;i+sold_size<s.size();i++)
        {
            if(s.substr(i,sold_size)==sold)
            {
                s.erase(i,sold_size);
                s.insert(i,snew);
                i+=snew.size();
            }
        }
    }
    // 使用迭代器 转换了下标
    void replaceString2(string& s,string& sold, string& snew)
    {
        size_t sold_size=sold.size();
        for(auto beg=s.begin(); distance(beg,s.end()) >=distance(sold.begin(),sold.end());beg++)
        {
            if(s.substr(beg-s.begin(),sold_size)==sold)
            {
                s.erase(beg-s.begin(),sold_size);
                s.insert(beg-s.begin(),snew);
                advance(beg,snew.size());
            }
        }
    }
    
    
    // 完全使用迭代器
    void replaceString(string& s,string& sold, string& snew)
    {
        size_t sold_size=sold.size();
        for(auto beg=s.begin(); distance(beg,s.end()) >=distance(sold.begin(),sold.end());beg++)
        {
            // if(s.substr(beg-s.begin(),sold_size)==sold)
            if(string(beg,beg+sold.size())==sold) 
            {
                beg=s.erase(beg,beg+sold_size);
                beg=s.insert(beg,snew.begin(),snew.end());
                advance(beg,snew.size());
            }
        }
    }
    
    int main(int argc, char const *argv[])
    {
        {
            string s="123 456 789 ";
            string sold="456";
            string snew="AAAA";
            replaceString(s,sold,snew);
            cout << s <<endl;
        }
    
    
    
         {
            string s="123 456 789 ";
            string sold="456";
            string snew="AAAA";
            replaceString0(s,sold,snew);
            cout << s <<endl;
        }
       
        while(1);
    
    
        return 0;
    }
    
    

    9.45

    9.46

    /*
    9.45
    接受一个表示名字的string参数和两个分别表示前缀(如“Mr."或”Ms.“)和后缀(Jr或III)的字符串。
    使用迭代器及insert和append函数将前缀和后缀加到给定的名字中,将生成的新string返回。
    
    9.46
    重写上一题的函数,这次使用位置和长度来管理string,并只使用insert
     */
    
    #include "include.h"
    
    
    string fullName(const string& s,const string& before,const string& after)
    {
        string full(s);
        full.insert(full.begin(),before.begin(),before.end());
        full.append(after);
        return full;
    }
    
    
    string fullName2(const string& s,const string& before,const string& after)
    {
        string full(s);
        full.insert(0,before);
        full.insert(full.size(),after);
        return full;
    }
    
    
    
    
    int main(int argc, char const *argv[])
    {
    
        cout << fullName("layty","Mr."," good")<<endl;
        cout << fullName2("layty","Mr."," good")<<endl;
    
        while(1);
        return 0;
    }
    
    

    9.47

    
    /*
    编写程序,首先查找string "ab2c3d7R4E6"中的每个数字字符,然后查找其中每个字母字符。编写两个版本的程序,第一个要使用find_fisrt_of,第二个要使用 find_first_not_of
    */
    #include "include.h"
    void find1(const string& s)
    {
        string number("0123456789");
        string abc;
        for(int i=0;i<26;i++)
        {
            abc.push_back('a'+i);
            abc.push_back('A'+i);
        }
    
        string::size_type pos=0;
        while( (pos=s.find_first_of(number,pos)) != string::npos)
        {
            cout << s[pos]<<endl;
            pos++;        
        }
    
        pos=0;
        while( (pos=s.find_first_of(abc,pos)) != string::npos)
        {
            cout << s[pos]<<endl;
            pos++;        
        }
    
        //----------------------------------------------------------
        pos=0;
        while( (pos=s.find_first_not_of(number,pos)) != string::npos)
        {
            cout << s[pos]<<endl;
            pos++;        
        }
    
        pos=0;
        while( (pos=s.find_first_not_of(abc,pos)) != string::npos)
        {
            cout << s[pos]<<endl;
            pos++;        
        }
    
    
    }
    
    
    
    
    int main(int argc, char const *argv[])
    {
        find1("123ABC456");
        while(1);
        return 0;
    }
    
    

    9.48

    假定name和numbers的定义如325页所示,number.find(name)返回什么?
    
    string name = "AnnaBelle";
    string number = "0123456789";
    auto result = number.find(name);
    if (result == string::npos) {
        cout << "npos" << endl;
    }
    
    返回 string::npos
    

    9.49

    /*
    如果一个字母延伸要中线之上,如d或f,则称其有上出头部分。如果延伸到中线之下,则称其有下出头部分。编写程序,读入一个单词文件,输出最长的既不包含上出头部分,也不包含下出头部分的单词。
    */
    #include <fstream>
    #include "include.h"
    
    int main(int argc, char const *argv[])
    {
        ifstream file("E:\Reading\C++\C+++Primer\CppPrimer-master\CppPrimer-master\ch09\ex9_49.cpp");
        if(!file) 
        {
            cout << "file open filed"<<endl;
            while(1);
            return -1;
        }
    
        string s;
        string get;
        while(file>>s)
        {
            if(s.find_first_not_of("aceimnorsuvwxz")==string::npos)
            {
                if(get.size()<s.size())
                    get=s;
            }
        }
        cout << "get: "<<get <<endl;
    
        while(1);
        return 0;
    }
    
    

    9.50

    /*
    编写程序处理一个vector,其元素都表示整形值。计算vector中所有元素之和。修改程序,使之计算表示浮点值的string之和
    */
    
    #include "include.h"
    int sum_int(const vector<string>& s)
    {
        int  n=0;
        for(auto ch : s)
        {   
            if(ch.find_first_of("0123456789")!=string::npos)
                if(ch.substr(ch.find_first_of("+-.0123456789")).size())
                {
                    n+=stoi(ch);
                }
    
        }
        return n;
    }
    
    double sum_double(const vector<string>& s)
    {
        double  n=0;
        for(auto ch : s)
        {   
            if(ch.find_first_of("0123456789")!=string::npos)
                if(ch.substr(ch.find_first_of("+-.0123456789")).size())
                {
                    n+=stod(ch);
                }
    
        }
        return n;
    }
    
    
    int main(int argc, char const *argv[])
    {
        vector<string> s={"---","2.1","2.1","-3"};
        cout << "sum="<<sum_int(s)<<endl;
        cout << "sum="<<sum_double(s)<<endl;
        while(1);
        return 0;
    }
    
    

    9.51

    /*
    设计一个类,它有三个unsigned成员,分别表示年、月和日。为其编写构造函数,接受一个表示日期的string参数。你的构造函数应该能处理不同数据格式,如January 1,1900、1/1/1990、Jan 1 1900等。
    */
    #include "include.h"
    #include <array>
    
    
    class mydate
    {
    private:
        /* data */
        unsigned int year=1990;
        unsigned int month=1;
        unsigned int day=1;
    public:
        mydate(const string& s);
        ~mydate();
    };
    
    mydate::mydate(const string& s1="")
    {
        string s(s1);
        if(s.empty()) return;
    
        string::size_type pos;
        string::size_type year_pos,month_pos;
        string::size_type pos_day,pos_month,pos_year;
        if((pos=s.find("/"))!= string::npos) // 1/1/1990
        {
            // day
            s=s.substr(s.find_first_of("0123456789"));
            day=stoul(s,&pos_day);
            // month
            s=s.substr(s.find_first_of("0123456789",pos_day));
            month=stoul(s,&pos_month);
            // year
            s=s.substr(s.find_first_of("0123456789",pos_month));
            year=stoul(s);
    
        } 
        else    //Jan 1 1900
        {
            std::array<std::string, 12> month_names{"Jan", "Feb", "Mar", "Apr", "May", "Jun","Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
            for(int i=0;i<12;i++)
            {
                if(s.find(month_names[i])!=string::npos)
                {
                     month=i+1;
                     break;
                }   
            }
            // day
            s=s.substr(s.find_first_of("0123456789"));
            day=stoul(s,&pos_day);
            // year
            s=s.substr(s.find_first_of("0123456789",pos_day));
            year=stoul(s);
    
    
            
        }
        
        cout<< "year="<<year<<" month="<<month<<" day="<<day<<endl;
    }
    
    mydate::~mydate()
    {
    }
    
    
    
    
    int main(int argc, char const *argv[])
    {
        mydate("3/4/2021");
        mydate("Dec 2 2022");
        mydate("January 1,2023");
        
        while(1);
        return 0;
    }
    
    

    9.52

    #include "include.h"
    
    #include <stack>
    
    
    int main(int argc, char const *argv[])
    {
    
        // 1*(2+10)-11
    
        stack<string> s;
    
    
        string  abc="1*(2+10)-1";
    
    
        string num;
        string::size_type i=0;
        for(auto ch : abc)
        {
            i++;
    
            if(ch>='0' && ch <='9')
            {
                num.append(string(1,ch));
                if(i==abc.size())
                {
                    s.push(num);
                }
            }
            else
            {
                if(!num.empty())
                {
                    s.push(num);
                }
                s.push(string(1,ch));
                num.erase();
            }
        }
        while(!s.empty())
        {
            cout<<s.top()<<endl;
            s.pop();
        }
    
    
    
        auto& expr = "This is (Mooophy(awesome)((((wooooooooo))))) and (ocxs) over";
    
        stack<char> s1;
    
        int ok=0;
    
        for(auto ch: expr)
        {
            s1.push(ch);
            if(ch=='(')  ok++;
            if(ch==')' && ok)
            {
                while(s1.top()!='(')
                {
                    s1.pop();
                }
                s1.pop();
                s1.push('#');
                ok--;
            }
        }
    
        string output;
        for (; !s1.empty(); s1.pop()) output.insert(output.begin(), s1.top());
        cout << output << endl; // "This is # and # over"
    
    
    
    
    
    
    
        while(1);
        return 0;
    }
    
    
  • 相关阅读:
    javaSE基础(六)--IO流
    javaSE基础(五)--JDBC
    javaSE基础(四)--Map集合
    javaSE基础(三)--List集合
    javaSE基础(二)
    javaSE基础(一)
    eclipse快捷键大全
    mybatis学习-基础
    工厂模式
    GC日志和jvm内存的分代
  • 原文地址:https://www.cnblogs.com/zongzi10010/p/12157862.html
Copyright © 2011-2022 走看看