• cppPrimer学习12th



    title: cppPrimer学习12th
    date: 2020/2/25 18:47:37
    toc: true

    cppPrimer学习12th

    12.1

    b1 有4个
    b2 元素销毁了
    

    12.2

    // 12.2 编写你自己的StrBlob类,包含const版本的front和back
    
    #include "../include/include.h"
    #include <initializer_list>
    #include <memory>
    #include <exception>
    class StrBlob
    {
    
    public:
        typedef vector<string>::size_type size_type;
        () : data(make_shared<vector<string>>()) {}
        StrBlob(initializer_list<string> li) : data(make_shared<vector<string>>(li)) {}
        size_type size() const
        {
            return data->size();
        }
        bool empty() const
        {
            return data->empty();
        }
    
        void push_back(const string &s)
        {
            data->push_back(s);
        }
        void pop_back();
    
        string &front();
        string &back();
        const string &front() const;
        const string &back() const;
    
        ~StrBlob();
    
    private:
        shared_ptr<vector<string>> data;
        void check(size_type i, const string &message) const
        {
            if (i >= data->size())
                throw std::out_of_range(message);
        }
    };
    
    StrBlob::~StrBlob()
    {
    }
    
    string &StrBlob::front()
    {
        check(0, "front on empty StrBlob");
        return data->front();
    }
    string &StrBlob::back()
    {
        check(0, "back on empty StrBlob");
        return data->back();
    }
    const string &StrBlob::front() const
    {
        check(0, "front on empty StrBlob");
        return data->front();
    }
    const string &StrBlob::back() const
    {
        check(0, "back on empty StrBlob");
        return data->back();
    }
    
    void StrBlob::pop_back()
    {
        check(0, "pop_back on empty StrBlob");
        data->pop_back();
    }
    
    int main(int argc, const char **argv)
    {
    
        StrBlob csb{"1", "2", "3"};
        StrBlob sb{"A1", "A2", "A3"};
    
        std::cout << csb.front() << " " << csb.back() << std::endl;
        sb.back() = "change";
        std::cout << sb.front() << " " << sb.back() << std::endl;
        while (1)
            ;
        return 0;
    }
    

    12.3

    不需要,因为这个操作本身会改变data指向的内容
    

    12.4

    size>=0  size_type 是unsigned的
    

    12.5

    如果有 initialize_list explicit的构造函数  那么就不能使用隐式转换了
    
    没有的优点:
    在需要 StrBlob的地方可以自动进行列表转换,比如使用一个类 StrBlob=("1","2");
    
    缺点:
    我们总是使用构造函数来构造一个临时的StrBlob对象
    
    反之
    编译器不会在自动转换中使用此构造函数,我们可以清楚地知道我们使用了哪个类
    

    12.6

    /*
    编写函数,返回一个动态分配的int的vector。将此vector传递给另一个函数。这个函数读取标准输入,
    将读入的值保存在vector中。再将vector传递给另一个函数,打印读入的值。记得在恰当的时刻delete vector
    */
    #include <vector>
    #include <memory>
    #include <iostream>
    
    using namespace std;
    
    vector<int> *get_vector_int_pt(void)
    {
        return new vector<int>();
    }
    
    vector<int> *put_vector_int_pt(vector<int> *pt)
    {
        int num;
        while (cin >> num)
            pt->push_back(num);
    
        return pt;
    }
    
    void show_vector_int_pt(vector<int> *pt)
    {
        for (int a : *pt)
            cout << a << " ";
        cout << endl;
    }
    
    int main(int argc, char const *argv[])
    {
        vector<int> *t = get_vector_int_pt();
        put_vector_int_pt(t);
        show_vector_int_pt(t);
        delete t;
    
        while (1)
            ;
        return 0;
    }
    
    

    12.7

    /*
    12.7 使用 shared_ptr
    编写函数,返回一个动态分配的int的vector。将此vector传递给另一个函数。这个函数读取标准输入,
    将读入的值保存在vector中。再将vector传递给另一个函数,打印读入的值。记得在恰当的时刻delete vector
    */
    #include <vector>
    #include <memory>
    #include <iostream>
    
    using namespace std;
    
    shared_ptr<vector<int>> get_vector_int_pt(void)
    {
        return make_shared<vector<int>>();
    }
    
    shared_ptr<vector<int>> put_vector_int_pt(shared_ptr<vector<int>> pt)
    {
        int num;
        while (cin >> num)
            pt->push_back(num);
    
        return pt;
    }
    
    void show_vector_int_pt(shared_ptr<vector<int>> pt)
    {
        for (int a : *pt)
            cout << a << " ";
        cout << endl;
    }
    
    int main(int argc, char const *argv[])
    {
        shared_ptr<vector<int>> t = get_vector_int_pt();
        put_vector_int_pt(t);
        show_vector_int_pt(t);
    
        while (1)
            ;
        return 0;
    }
    

    12.8

    p 是一个指针,转换为bool, 但是p原来的内存永远不会释放了
    
    

    12.9

    r和q指向42,但是r原来的内存无法释放,同时两个指针指向同一个地方
    可能释放了一个指针后,另一个没释放的指向已经释放的内存,也就是空悬指针问题
    
    r2指向q2,同时原来r2 内存释放
    

    12.10

    void process(shared_ptr ptr)  // 注意这里是值拷贝,也就是引用+1
    {
        // 使用ptr
    }
    //离开后释放ptr
    
    //p 指向int
    shared_ptr<int>p(new int(42));
    process(shared_ptr<int>p);
    这里p不会被释放的
    p.reset(); //执行释放
    
    这段代码本身没有问题
    

    12.11

    有两个共享指针指向了同一个区域
    也就是退出函数后 p的内存已经被这个临时共享指针对象释放了
    

    12.12

    void process(shared_ptr ptr)  // 注意这里是值拷贝,也就是引用+1
    {
        // 使用ptr
    }
    //离开后释放ptr
    
    a 合法
    b,c 非法,没有隐式转换的构造函数
    d 合法,但是会删除p的内存
    

    12.13

    sp指向int
    p 释放了sp的内容,但是sp的计数还在,所以sp会再次释放
    也就是释放了两次
    

    12.14

    12.15

    //shared_ptr<connection>p (&c,[](struct connection*p){disconnect(*p);});
    
    
    /*
    12.14+12.15
    智能指针与异常结合的使用
    当异常发生后,我们在异常发生之后的语句无法执行,比如一些资源清理操作,这个时候可以把清理动作作为一个共享指针的delte参数
    shared_ptr<connection> end_link(&linkme, try_end_link);  try_end_link 在程序结束或者异常后能够执行
    */
    
    #include <vector>
    #include <memory>
    #include <iostream>
    
    using namespace std;
    
    struct connection
    {
        int fd;
    };
    
    struct disconnection
    {
        int fd;
        int port;
    };
    
    connection
    connect(struct disconnection *t)
    {
        struct connection ret;
        ret.fd = t->port + 1;
        cout << "link to port:" << t->port << endl;
        return ret;
    }
    
    disconnection
    disconnect(struct connection *t)
    {
        struct disconnection ret;
        if (t->fd > 0)
        {
            ret.fd = -1;
            ret.port = t->fd - 1;
            cout << "break LINK to port:" << ret.port << endl;
            t->fd = -1;
        }
    
        return ret;
    }
    
    void try_end_link(struct connection *t)
    {
        cout << "By shared_ptr" << endl;
        disconnect(t);
    }
    
    int main(int argc, char const *argv[])
    {
        {
            struct disconnection unlinkme = {-1, 20};
            connection linkme = connect(&unlinkme);
            // disconnect(&linkme);
            //shared_ptr<connection> end_link(&linkme, try_end_link);
            shared_ptr<connection> end_link(&linkme, [](struct connection *t) {cout << "By shared_ptr" << endl;disconnect(t); });
        }
        while (1)
            ;
        return 0;
    }
    
    

    12.16

    /*
    12.16 给一个unique_ptr 赋值观察错误
    */
    #include <iostream>
    #include <memory>
    using namespace std;
    
    int main(int argc, char const *argv[])
    {
        unique_ptr<int> p(new int(3));
        int *pint = new int(3);
        unique_ptr<int> p_unique(new int(3));
    
        //unique_ptr<int> s(3);
    
        // no known conversion for argument 1 from 'int*' to 'std::nullptr_t'
        //p = pint;
    
        // use of deleted function 'std::unique_ptr<_Tp, _Dp>& std::unique_ptr<_Tp, _Dp>::operator=(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]'
        //unique_ptr& operator=(const unique_ptr&) = delete;
        //p = p_unique;
    
        while (1)
            ;
        return 0;
    }
    
    

    12.17

    下面的unique_ptr声明中,哪些是合法的,哪些可能导致后续的程序错误?
    int ix = 1024, *pi = &ix, *pi2 = new int(20478);
    typedef unique_ptr<int> IntP;
    
    
    (a) IntP p0(ix);  非法,无法将int转为指针   
    (b) IntP p1(pi);  合法,但是----原始内容是int 不是new出来的,无法del
    (c) IntP p2(pi2); 合法,两个指针指向同一个内存                           
    (d) IntP p3(&ix); 同b非法
    (e) IntP p4(new int(2048)); 合法
    (f) IntP p5(p2.get());  合法,但是----两个指针指向同一个地方
    

    12.18

    release 是放弃控制权清空unique_ptr 
    release操作是用来将对象的所有权转移给另一个unique_ptr的
    
    share_ptr 本身就没有控制权,可以相互拷贝赋值
    

    12.19

    12.20

    /*
    12.19 
    12.20 读入文件 使用这个类
    
    一个 StrBlob类,底层数据是指向 vector<string> 的指针
    一个 StrBlob_ptr类,可以认为是StrBlob类的指针类
    
    定义  StrBlob类,数据成员是 vector<string> 的shared_ptr
            begin  指向第一个元素的 StrBlob_ptr 也就是cur=0?
            end                   最后一个元素的指针cur=size()   end是开区间,所以不用减1
    定义  StrBlob_ptr 类,指向 StrBlob类中的数据成员 *shared_ptr
            一个指向 vector<string> 的指针,带有小标
            *      获得string
            ++     将下标++
    
    
    */
    
    #include <vector>
    #include <string>
    #include <memory>
    #include <initializer_list>
    #include <exception>
    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    class StrBlob_ptr;
    
    class StrBlob
    {
        using Blob_size_type = vector<string>::size_type;
    
        friend class StrBlob_ptr;
    
    private:
        /* data */
        shared_ptr<vector<string>> data;
    
    public:
        StrBlob() : data(make_shared<vector<string>>()) {}
        StrBlob(initializer_list<string> li) : data(make_shared<vector<string>>(li)) {}
    
        StrBlob_ptr begin(); //{ return StrBlob_ptr(*this); }
        StrBlob_ptr end();   //{ return StrBlob_ptr(*this, data->size()); }
    
        Blob_size_type size() const
        {
            return data->size();
        }
    
        bool empty() const
        {
            return data->empty();
        }
    
        bool check(Blob_size_type has, const string &msg) const
        {
            if (has >= data->size())
                throw std::out_of_range(msg);
        }
    
        void push_back(string &s)
        {
            data->push_back(s);
        }
        void pop_back()
        {
            check(0, "pop_back");
            data->pop_back();
        }
    
        string &front()
        {
            check(0, "front");
            return data->front();
        }
    
        string &back()
        {
            check(0, "back");
            return data->back();
        }
    
        const string &front() const
        {
            check(0, "front");
            return data->front();
        }
    
        const string &back() const
        {
            check(0, "back");
            return data->back();
        }
    
        ~StrBlob() {}
    };
    
    class StrBlob_ptr
    {
    private:
        // 底层指针指向的内容是 shared_ptr,可能存在释放的情况
        weak_ptr<vector<string>> ptr;
        int cur;
        shared_ptr<vector<string>> check(int size, const string msg) const;
    
    public:
        // 构造函数,指向空的ptr
        StrBlob_ptr() : cur(0) {}
        StrBlob_ptr(StrBlob &s, int offset = 0) : ptr(s.data), cur(offset) {}
        ~StrBlob_ptr() {}
    
        // * 解引用
        string &deref() const;
        StrBlob_ptr &increase_ref();
        // 同时需要定义!= 这里应该还要判断 p的指向是否相同
        bool operator!=(const StrBlob_ptr &p) { return p.cur != cur; }
    };
    
    shared_ptr<vector<string>> StrBlob_ptr::check(int size, const string msg) const
    {
        auto ptr_get = ptr.lock();
        if (!ptr_get)
            throw runtime_error(msg);
        if (size >= ptr_get->size())
            throw out_of_range(msg);
        return ptr_get;
    }
    
    string &StrBlob_ptr::deref() const
    {
        auto ptr_get = check(cur, "get shared_ptr");
        return (*ptr_get)[cur];
    }
    
    StrBlob_ptr &StrBlob_ptr::increase_ref()
    {
        check(cur, "get shared_ptr");
        cur++;
        return *this;
    }
    
    /*
     *   这两个函数一定要放到 StrBlob_ptr 这个类下面定义,因为用到了StrBlob_ptr具体的构造函数; 即使最开始已经声明了
     *    
     *
     *
    */
    StrBlob_ptr StrBlob::begin()
    {
        return StrBlob_ptr(*this);
    }
    StrBlob_ptr StrBlob::end()
    {
        return StrBlob_ptr(*this, data->size());
    }
    
    int main(int argc, const char **argv)
    {
    
        StrBlob csb{"1", "2", "3"};
        StrBlob sb{"A1", "A2", "A3"};
    
        std::cout << csb.front() << " " << csb.back() << std::endl;
        sb.back() = "change";
        std::cout << sb.front() << " " << sb.back() << std::endl;
    
        cout << "vector string :" << endl;
        for (StrBlob_ptr ch = sb.begin(); ch != sb.end(); ch.increase_ref())
            cout << ch.deref() << ",";
        cout << endl;
    
        ifstream ifile("./12.19.cpp");
        StrBlob fs_blob;
        for (string str; getline(ifile, str);)
            fs_blob.push_back(str);
    
        cout << "file string :" << endl;
        for (StrBlob_ptr ch = fs_blob.begin(); ch != fs_blob.end(); ch.increase_ref())
            cout << ch.deref() << endl;
    
        while (1)
            ;
        return 0;
    }
    

    12.21

    原来的好,原来的好看 哈哈哈

    12.22

    /*
    12.19 
    12.20 读入文件 使用这个类
    12.22 使用  const StrBlob类
    			strBlob begin end 返回const
                底层指针是个const,只有在构造的时候赋值
                解引用的时候返回const  
    
    一个 StrBlob类,底层数据是指向 vector<string> 的指针
    一个 StrBlob_ptr类,可以认为是StrBlob类的指针类
    
    定义  StrBlob类,数据成员是 vector<string> 的shared_ptr
            begin  指向第一个元素的 StrBlob_ptr 也就是cur=0?
            end                   最后一个元素的指针cur=size()   end是开区间,所以不用减1
    定义  StrBlob_ptr 类,指向 StrBlob类中的数据成员 *shared_ptr
            一个指向 vector<string> 的指针,带有小标
            *      获得string
            ++     将下标++
    
    
    */
    
    #include <vector>
    #include <string>
    #include <memory>
    #include <initializer_list>
    #include <exception>
    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    class StrBlob_ptr;
    
    class StrBlob
    {
        using Blob_size_type = vector<string>::size_type;
    
        friend class StrBlob_ptr;
    
    private:
        /* data */
        shared_ptr<vector<string>> data;
    
    public:
        StrBlob() : data(make_shared<vector<string>>()) {}
        StrBlob(initializer_list<string> li) : data(make_shared<vector<string>>(li)) {}
    
        StrBlob_ptr begin() const; //{ return StrBlob_ptr(*this); }
        StrBlob_ptr end() const;   //{ return StrBlob_ptr(*this, data->size()); }
    
        Blob_size_type size() const
        {
            return data->size();
        }
    
        bool empty() const
        {
            return data->empty();
        }
    
        bool check(Blob_size_type has, const string &msg) const
        {
            if (has >= data->size())
                throw std::out_of_range(msg);
        }
    
        void push_back(string &s)
        {
            data->push_back(s);
        }
        void pop_back()
        {
            check(0, "pop_back");
            data->pop_back();
        }
    
        string &front()
        {
            check(0, "front");
            return data->front();
        }
    
        string &back()
        {
            check(0, "back");
            return data->back();
        }
    
        const string &front() const
        {
            check(0, "front");
            return data->front();
        }
    
        const string &back() const
        {
            check(0, "back");
            return data->back();
        }
    
        ~StrBlob() {}
    };
    
    class StrBlob_ptr
    {
    private:
        // 底层指针指向的内容是 shared_ptr,可能存在释放的情况
        weak_ptr<vector<string>> ptr;
        int cur;
        shared_ptr<vector<string>> check(int size, const string msg) const;
    
    public:
        // 构造函数,指向空的ptr
        StrBlob_ptr() : cur(0) {}
        StrBlob_ptr(const StrBlob &s, int offset = 0) : ptr(s.data), cur(offset) {}
        ~StrBlob_ptr() {}
    
        // * 解引用
        const string &deref() const;
        StrBlob_ptr &increase_ref();
        // 同时需要定义!= 这里应该还要判断 p的指向是否相同
        bool operator!=(const StrBlob_ptr &p) { return p.cur != cur; }
    };
    
    shared_ptr<vector<string>> StrBlob_ptr::check(int size, const string msg) const
    {
        auto ptr_get = ptr.lock();
        if (!ptr_get)
            throw runtime_error(msg);
        if (size >= ptr_get->size())
            throw out_of_range(msg);
        return ptr_get;
    }
    
    const string &StrBlob_ptr::deref() const
    {
        auto ptr_get = check(cur, "get shared_ptr");
        return (*ptr_get)[cur];
    }
    
    StrBlob_ptr &StrBlob_ptr::increase_ref()
    {
        check(cur, "get shared_ptr");
        cur++;
        return *this;
    }
    
    /*
     *   这两个函数一定要放到 StrBlob_ptr 这个类下面定义,因为用到了StrBlob_ptr具体的构造函数; 即使最开始已经声明了
     *    
     *
     *
    */
    StrBlob_ptr StrBlob::begin() const
    {
        return StrBlob_ptr(*this);
    }
    StrBlob_ptr StrBlob::end() const
    {
        return StrBlob_ptr(*this, data->size());
    }
    
    int main(int argc, const char **argv)
    {
    
        const StrBlob csb{"1", "2", "3"};
        StrBlob sb{"A1", "A2", "A3"};
    
        std::cout << csb.front() << " " << csb.back() << std::endl;
        sb.back() = "change";
        std::cout << sb.front() << " " << sb.back() << std::endl;
    
        cout << "vector string :" << endl;
        for (StrBlob_ptr ch = sb.begin(); ch != sb.end(); ch.increase_ref())
            cout << ch.deref() << ",";
        cout << endl;
    
        ifstream ifile("./12.19.cpp");
        StrBlob fs_blob;
        for (string str; getline(ifile, str);)
            fs_blob.push_back(str);
    
        cout << "file string :" << endl;
        for (StrBlob_ptr ch = fs_blob.begin(); ch != fs_blob.end(); ch.increase_ref())
            cout << ch.deref() << endl;
    
        while (1)
            ;
        return 0;
    }
    

    12.23

    /*
    编写一个程序,连接两个字符串字面值常量,将结果保存在一个动态分配的char数组中。重写这个程序,连接两个标准库string对象
    */
    #include <string>
    #include <string.h>
    #include <iostream>
    
    using std::cout;
    using std::endl;
    using std::string;
    
    int main(int argc, char const *argv[])
    {
    
        const char *c1 = "hello";
        const char *c2 = " world";
        char *c3 = new char[strlen(c1) + strlen(c2) + 1];
        memcpy(c3, c1, strlen(c1));
        memcpy(c3 + strlen(c1), c2, strlen(c2));
        c3[strlen(c1) + strlen(c2)] = 0;
    
        string s1(c1), s2(c2);
        string s3 = s1 + s2;
    
        char *s4 = new char[s3.length()];
        strcpy(s4, s3.c_str());
    
        cout << string(c3) << endl;
        cout << s3 << endl;
        cout << s4 << endl;
    
        while (1)
            ;
        return 0;
    }
    
    

    12.24

    /*12.24:编写一个程序,从标准输入读取一个字符串,存入一个动态分配的字符数组中。描述你的程序如何处理变长。测试你的程序,输入一个超出你分配的数组长度的字符串*/
    
    #include <iostream>
    using namespace std;
    
    int main(int argc, char const *argv[])
    {
        char c;
        char *s = new char[4];
        int i = 0;
        int len = 4;
    
        while (cin >> c)
        {
            if (i >= len - 1)
            {
                char *s_new = new char[len * 2];
                memcpy(s_new, s, len - 1);
                len *= 2;
                delete[] s;
                s = s_new;
                cout << "before len:" << len / 2 << ",arter len=" << len << " last char is " << s_new[i - 1] << endl;
            }
            if (c == '
    ' || c == '
    ')
                break;
            s[i++] = c;
        }
        s[i] = 0;
        cout << s << endl;
    
        while (1)
            ;
        return 0;
    }
    
    

    12.25

    int *pa = new int[10];
    如何释放pa?
        delete[] pa
    

    12.26

    /*
    12.26  使用 allocater 替代new
    */
    #include <iostream>
    #include <string>
    #include <memory>
    using namespace std;
    
    void old_test()
    {
        cout << "use new[] " << endl;
        string *const p = new string[10];
        string s, *q = p;
        while (cin >> s && q != p + 10)
        {
            *q++ = s; // q=s q++
        }
        const size_t size = q - p; // 实际使用的内存
        for (int i = 0; i < size; i++)
            cout << p[i] << endl;
        delete[] p;
        cout << "end of use new[] " << endl;
    }
    
    void new_test()
    {
        cout << "use allocater " << endl;
        allocator<string> allocator_string;
        auto const p = allocator_string.allocate(10);
        string *q = p;
    
        string s;
        while (cin >> s && q != p + 10)
        {
            allocator_string.construct(q++, s);
        }
        for (size_t i = 0; i < q - p; i++)
        {
            cout << p[i] << endl;
        }
        while (q != p)
        {
            allocator_string.destroy(--q);
        }
        allocator_string.deallocate(p, 100);
        cout << "end of use allocater " << endl;
    }
    
    int main(int argc, char const *argv[])
    {
        /* code */
    
        //old_test();
    
        new_test();
        while (1)
            ;
    
        return 0;
    }
    
    

    12.27

    #include <string>
    #include <map>
    #include <set>
    #include <iostream>
    #include <sstream>
    #include <fstream>
    #include <vector>
    #include <memory>
    
    using namespace std;
    
    // 0. 没有使用 Query类保存结果,这里的简单例子直接从 TextQuery取得结果
    // 1. 使用 vector<string> 保存每行文字
    // 2. 每个string 有一个set 保存行号
    // 3. 使用 map<string,set>绑定这个数据
    
    class TextQuery
    {
    private:
        /* data */
        vector<string> txtline;
        map<string, set<int>> data;
    
    public:
        TextQuery(ifstream &file);
        ~TextQuery(){};
        ostream &GetWant(ostream &out, string ch);
    };
    
    TextQuery::TextQuery(ifstream &file)
    {
        // 读入文件到文件流,保存每一行到vector<string>
        string s;
        int line_at = 0;
        while (getline(file, s))
        {
            txtline.push_back(s);
            string ch;
            istringstream ss(s);
            while (ss >> ch)
            {
                data[ch].insert(line_at);
            }
            line_at++;
        }
    }
    
    ostream &TextQuery::GetWant(ostream &out, string ch)
    {
        out << "[" << ch << "]:" << endl;
        for (auto i = data[ch].begin(); i != data[ch].end(); i++)
            out << "Line[" << (*i) + 1 << "]: " << txtline[*i] << endl;
        return out;
    }
    
    void runQueries(ifstream &file)
    {
        // 从文件流建立查询的数据
        TextQuery tq(file);
        while (true)
        {
            cout << "Enter what you want to find?" << endl;
            string s;
            if (!(cin >> s) || s == "q")
                break;
            tq.GetWant(cout, s);
        }
    }
    
    int main(int argc, char const *argv[])
    {
        ifstream fs("D:\a.txt");
        runQueries(fs);
        return 0;
    }
    
    

    12.27.1

    #include <string>
    #include <map>
    #include <set>
    #include <iostream>
    #include <sstream>
    #include <fstream>
    #include <vector>
    #include <memory>
    
    using namespace std;
    
    /*
        定义一个类 保存 string,行号,以及一个指向txt的指针
    */
    class ResultQuery
    {
        friend ostream &print(ostream &, const ResultQuery &);
    
    public:
        // 单词
        string w;
        // 行号的列表
        shared_ptr<set<int>> lines;
        // 全部的文本,可以通过行号寻找
        shared_ptr<vector<string>> txtline;
    
    public:
        ResultQuery(string word, shared_ptr<set<int>> line_num, shared_ptr<vector<string>> txt) : w(word), lines(line_num), txtline(txt){};
        ~ResultQuery(){};
    };
    
    class TextQuery
    {
    private:
        /* data */
        shared_ptr<vector<string>> txtline;
        // 因为在ret里面共享的是set的行号,所以这里也是行号共享指针,而不是整个map
        map<string, shared_ptr<set<int>>> data;
    
    public:
        TextQuery(ifstream &file);
        ResultQuery Query(string &w);
        ~TextQuery(){};
    };
    
    TextQuery::TextQuery(ifstream &file) : txtline(new vector<string>)
    {
        // 读入文件到文件流,保存每一行到vector<string>
        string s;
        int line_at = 0;
        while (getline(file, s))
        {
            txtline->push_back(s);
            string ch;
            istringstream ss(s);
            while (ss >> ch)
            {
                if (!data[ch])
                    data[ch].reset(new set<int>);
                data[ch]->insert(line_at);
            }
            line_at++;
        }
    }
    
    ResultQuery TextQuery::Query(string &w)
    {
        static shared_ptr<std::set<int>> nodate(new std::set<int>);
        auto found = data.find(w);
        if (found == data.end())
            return ResultQuery(w, nodate, txtline);
        else
            return ResultQuery(w, data[w], txtline);
    }
    //ostream &print(ostream &, const ResultQuery &)
    ostream &print(ostream &out, const ResultQuery &want)
    {
        out << "----------------------------------------------" << endl;
        out << "string:" << want.w << endl;
        out << "Txt List:" << endl;
        //if (want.lines) // 先要判断指针是否存在
        {
            for (auto ls : *(want.lines))
                out << ls << ":			" << want.txtline->at(ls) << endl;
            //qr.input->at(i)
        }
    
        out << "----------------------------------------------" << endl;
        return out;
    }
    
    void runQueries(ifstream &file)
    {
        // 从文件流建立查询的数据
        TextQuery tq(file);
        while (true)
        {
            cout << "Enter what you want to find?" << endl;
            string s;
            if (!(cin >> s) || s == "q")
                break;
            print(cout, tq.Query(s)) << endl;
        }
    }
    
    int main(int argc, char const *argv[])
    {
        ifstream fs("D:\a.txt");
        if (fs)
            runQueries(fs);
        else
            cout << "fs open failed " << endl;
    
        while (1)
            ;
        return 0;
    }
    
    

    12.28

    /*
    12.28:编写程序实现文本查询,不要定义类来管理数据,你的程序应该接受一个文件,并与用户交互来查询单词。
    使用vector、map和set容器来保存来自文件的数据并生成查询结果。
    */
    
    #include <string>
    #include <map>
    #include <set>
    #include <iostream>
    #include <sstream>
    #include <fstream>
    #include <vector>
    #include <memory>
    using namespace std;
    
    void test(ifstream &file)
    {
        vector<string> txtline;
        map<string, set<int>> num;
    
        // 读入文件到文件流,保存每一行到vector<string>
        string s;
        int line_at = 0;
        while (getline(file, s))
        {
            txtline.push_back(s);
            string ch;
            istringstream ss(s);
            while (ss >> ch)
            {
                num[ch].insert(line_at);
            }
            line_at++;
        }
    
        string ch;
        cout << "pls input word to search" << endl;
        while (cin >> ch)
        {
            cout << "find " << ch << endl;
            for (auto i : num[ch])
            {
                cout << "line:" << i << "]:" << txtline[i] << endl;
            }
        }
    }
    
    int main(int argc, char const *argv[])
    {
        ifstream fin("C:\JLink.log");
        if (fin)
            test(fin);
        else
            cout << "check file" << endl;
        while (1)
            ;
        return 0;
    }
    
    

    12.29

    差不多
    

    12.31

    vector 会有重复行号,需要处理相同行号
    

    12.32

    /*
    12.32
    重写TextQuery和QueryResult类,用StrBlob代替vector<vector>保存输入文件
    
    TextQuery 使用StrBlob  存储shared_ptr<vector<string>>  文本
    具体查询打印的时候,我们要从 *(StrBlob.ptr) 中取小标
    也就是 使用 StrBlob_ptr 这个类指向了StrBlob中vector[下标]
    
    github的答案是这里 使用 shared_ptr 执行StrBlob 也就是  shared_ptr<StrBlob> 的操作,
    */
    
    /*
    12.19 
    12.20 读入文件 使用这个类
    12.22 使用  const StrBlob类
    			strBlob begin end 返回const
                底层指针是个const,只有在构造的时候赋值
                解引用的时候返回const  
    
    一个 StrBlob类,底层数据是指向 vector<string> 的指针
    一个 StrBlob_ptr类,可以认为是StrBlob类的指针类
    
    定义  StrBlob类,数据成员是 vector<string> 的shared_ptr
            begin  指向第一个元素的 StrBlob_ptr 也就是cur=0?
            end                   最后一个元素的指针cur=size()   end是开区间,所以不用减1
    定义  StrBlob_ptr 类,指向 StrBlob类中的数据成员 *shared_ptr
            一个指向 vector<string> 的指针,带有小标
            *      获得string
            ++     将下标++
    
    
    */
    
    #include <vector>
    #include <string>
    #include <memory>
    #include <initializer_list>
    #include <exception>
    #include <iostream>
    #include <fstream>
    #include <set>
    #include <map>
    #include <sstream>
    
    using namespace std;
    
    class StrBlob_ptr;
    
    class StrBlob
    {
        using Blob_size_type = vector<string>::size_type;
    
        friend class StrBlob_ptr;
    
    private:
        /* data */
        shared_ptr<vector<string>> data;
    
    public:
        StrBlob() : data(make_shared<vector<string>>()) {}
        StrBlob(initializer_list<string> li) : data(make_shared<vector<string>>(li)) {}
    
        StrBlob_ptr begin() const; //{ return StrBlob_ptr(*this); }
        StrBlob_ptr end() const;   //{ return StrBlob_ptr(*this, data->size()); }
    
        Blob_size_type size() const
        {
            return data->size();
        }
    
        bool empty() const
        {
            return data->empty();
        }
    
        bool check(Blob_size_type has, const string &msg) const
        {
            if (has >= data->size())
                throw std::out_of_range(msg);
        }
    
        void push_back(string &s)
        {
            data->push_back(s);
        }
        void pop_back()
        {
            check(0, "pop_back");
            data->pop_back();
        }
    
        string &front()
        {
            check(0, "front");
            return data->front();
        }
    
        string &back()
        {
            check(0, "back");
            return data->back();
        }
    
        const string &front() const
        {
            check(0, "front");
            return data->front();
        }
    
        const string &back() const
        {
            check(0, "back");
            return data->back();
        }
    
        ~StrBlob() {}
    };
    
    class StrBlob_ptr
    {
    private:
        // 底层指针指向的内容是 shared_ptr,可能存在释放的情况
        weak_ptr<vector<string>> ptr;
        int cur;
        shared_ptr<vector<string>> check(int size, const string msg) const;
    
    public:
        // 构造函数,指向空的ptr
        StrBlob_ptr() : cur(0) {}
        StrBlob_ptr(const StrBlob &s, int offset = 0) : ptr(s.data), cur(offset) {}
        ~StrBlob_ptr() {}
    
        // * 解引用
        const string &deref() const;
        StrBlob_ptr &increase_ref();
        // 同时需要定义!= 这里应该还要判断 p的指向是否相同
        bool operator!=(const StrBlob_ptr &p) { return p.cur != cur; }
    };
    
    shared_ptr<vector<string>> StrBlob_ptr::check(int size, const string msg) const
    {
        auto ptr_get = ptr.lock();
        if (!ptr_get)
            throw runtime_error(msg);
        if (size >= ptr_get->size())
            throw out_of_range(msg);
        return ptr_get;
    }
    
    const string &StrBlob_ptr::deref() const
    {
        auto ptr_get = check(cur, "get shared_ptr");
        return (*ptr_get)[cur];
    }
    
    StrBlob_ptr &StrBlob_ptr::increase_ref()
    {
        check(cur, "get shared_ptr");
        cur++;
        return *this;
    }
    
    /*
     *   这两个函数一定要放到 StrBlob_ptr 这个类下面定义,因为用到了StrBlob_ptr具体的构造函数; 即使最开始已经声明了
     *    
     *
     *
    */
    StrBlob_ptr StrBlob::begin() const
    {
        return StrBlob_ptr(*this);
    }
    StrBlob_ptr StrBlob::end() const
    {
        return StrBlob_ptr(*this, data->size());
    }
    
    /******************************************************************************************************************/
    
    class ResultQuery
    {
        friend ostream &print(ostream &, const ResultQuery &);
    
    public:
        // 单词
        string w;
        // 行号的列表
        shared_ptr<set<int>> lines;
        // 全部的文本,可以通过行号寻找
        StrBlob txtline; //----------modify
    
    public:
        ResultQuery(string word, shared_ptr<set<int>> line_num, StrBlob txt) : w(word), lines(line_num), txtline(txt){}; //----------modify
        ~ResultQuery(){};
    };
    
    class TextQuery
    {
    private:
        /* data */
        StrBlob txtline; //----------modify
        // 因为在ret里面共享的是set的行号,所以这里也是行号共享指针,而不是整个map
        map<string, shared_ptr<set<int>>> data;
    
    public:
        TextQuery(ifstream &file);
        ResultQuery Query(string &w);
        ~TextQuery(){};
    };
    
    TextQuery::TextQuery(ifstream &file) : txtline() //----------modify
    {
        // 读入文件到文件流,保存每一行到vector<string>
        string s;
        int line_at = 0;
        while (getline(file, s))
        {
            txtline.push_back(s); //----------modify
            string ch;
            istringstream ss(s);
            while (ss >> ch)
            {
                if (!data[ch])
                    data[ch].reset(new set<int>);
                data[ch]->insert(line_at);
            }
            line_at++;
        }
    }
    
    ResultQuery TextQuery::Query(string &w)
    {
        static shared_ptr<std::set<int>> nodate(new std::set<int>);
        auto found = data.find(w);
        if (found == data.end())
            return ResultQuery(w, nodate, txtline);
        else
            return ResultQuery(w, data[w], txtline);
    }
    //ostream &print(ostream &, const ResultQuery &)
    ostream &print(ostream &out, const ResultQuery &want)
    {
        out << "----------------------------------------------" << endl;
        out << "string:" << want.w << endl;
        out << "Txt List:" << endl;
        //if (want.lines) // 先要判断指针是否存在
        {
            for (auto ls : *(want.lines))
            {
                StrBlob_ptr xx(want.txtline, ls);             //----------modify
                out << ls << ":			" << xx.deref() << endl; //----------modify
            }
    
            //qr.input->at(i)
        }
    
        out << "----------------------------------------------" << endl;
        return out;
    }
    
    void runQueries(ifstream &file)
    {
        // 从文件流建立查询的数据
        TextQuery tq(file);
        while (true)
        {
            cout << "Enter what you want to find?" << endl;
            string s;
            if (!(cin >> s) || s == "q")
                break;
            print(cout, tq.Query(s)) << endl;
        }
    }
    
    int main(int argc, char const *argv[])
    {
        ifstream fs("D:\a.txt");
        if (fs)
            runQueries(fs);
        else
            cout << "fs open failed " << endl;
    
        while (1)
            ;
        return 0;
    }
    
    

    12.32.2

    /*
    12.32.2 
    完全使用 shared_ptr<StrBlob>  替换  shared_ptr<vector<string>>
    
    
    12.32
    重写TextQuery和QueryResult类,用StrBlob代替vector<vector>保存输入文件
    
    TextQuery 使用StrBlob  存储shared_ptr<vector<string>>  文本
    具体查询打印的时候,我们要从 *(StrBlob.ptr) 中取小标
    也就是 使用 StrBlob_ptr 这个类指向了StrBlob中vector[下标]
    
    github的答案是这里 使用 shared_ptr 执行StrBlob 也就是  shared_ptr<StrBlob> 的操作,
    */
    
    /*
    12.19 
    12.20 读入文件 使用这个类
    12.22 使用  const StrBlob类
    			strBlob begin end 返回const
                底层指针是个const,只有在构造的时候赋值
                解引用的时候返回const  
    
    一个 StrBlob类,底层数据是指向 vector<string> 的指针
    一个 StrBlob_ptr类,可以认为是StrBlob类的指针类
    
    定义  StrBlob类,数据成员是 vector<string> 的shared_ptr
            begin  指向第一个元素的 StrBlob_ptr 也就是cur=0?
            end                   最后一个元素的指针cur=size()   end是开区间,所以不用减1
    定义  StrBlob_ptr 类,指向 StrBlob类中的数据成员 *shared_ptr
            一个指向 vector<string> 的指针,带有小标
            *      获得string
            ++     将下标++
    
    
    */
    
    #include <vector>
    #include <string>
    #include <memory>
    #include <initializer_list>
    #include <exception>
    #include <iostream>
    #include <fstream>
    #include <set>
    #include <map>
    #include <sstream>
    
    using namespace std;
    
    class StrBlob_ptr;
    
    class StrBlob
    {
        using Blob_size_type = vector<string>::size_type;
    
        friend class StrBlob_ptr;
    
    private:
        /* data */
        shared_ptr<vector<string>> data;
    
    public:
        StrBlob() : data(make_shared<vector<string>>()) {}
        StrBlob(initializer_list<string> li) : data(make_shared<vector<string>>(li)) {}
    
        StrBlob_ptr begin() const; //{ return StrBlob_ptr(*this); }
        StrBlob_ptr end() const;   //{ return StrBlob_ptr(*this, data->size()); }
    
        Blob_size_type size() const
        {
            return data->size();
        }
    
        bool empty() const
        {
            return data->empty();
        }
    
        bool check(Blob_size_type has, const string &msg) const
        {
            if (has >= data->size())
                throw std::out_of_range(msg);
        }
    
        void push_back(string &s)
        {
            data->push_back(s);
        }
        void pop_back()
        {
            check(0, "pop_back");
            data->pop_back();
        }
    
        string &front()
        {
            check(0, "front");
            return data->front();
        }
    
        string &back()
        {
            check(0, "back");
            return data->back();
        }
    
        const string &front() const
        {
            check(0, "front");
            return data->front();
        }
    
        const string &back() const
        {
            check(0, "back");
            return data->back();
        }
    
        ~StrBlob() {}
    };
    
    class StrBlob_ptr
    {
    private:
        // 底层指针指向的内容是 shared_ptr,可能存在释放的情况
        weak_ptr<vector<string>> ptr;
        int cur;
        shared_ptr<vector<string>> check(int size, const string msg) const;
    
    public:
        // 构造函数,指向空的ptr
        StrBlob_ptr() : cur(0) {}
        StrBlob_ptr(const StrBlob &s, int offset = 0) : ptr(s.data), cur(offset) {}
        ~StrBlob_ptr() {}
    
        // * 解引用
        const string &deref() const;
        StrBlob_ptr &increase_ref();
        // 同时需要定义!= 这里应该还要判断 p的指向是否相同
        bool operator!=(const StrBlob_ptr &p) { return p.cur != cur; }
    };
    
    shared_ptr<vector<string>> StrBlob_ptr::check(int size, const string msg) const
    {
        auto ptr_get = ptr.lock();
        if (!ptr_get)
            throw runtime_error(msg);
        if (size >= ptr_get->size())
            throw out_of_range(msg);
        return ptr_get;
    }
    
    const string &StrBlob_ptr::deref() const
    {
        auto ptr_get = check(cur, "get shared_ptr");
        return (*ptr_get)[cur];
    }
    
    StrBlob_ptr &StrBlob_ptr::increase_ref()
    {
        check(cur, "get shared_ptr");
        cur++;
        return *this;
    }
    
    /*
     *   这两个函数一定要放到 StrBlob_ptr 这个类下面定义,因为用到了StrBlob_ptr具体的构造函数; 即使最开始已经声明了
     *    
     *
     *
    */
    StrBlob_ptr StrBlob::begin() const
    {
        return StrBlob_ptr(*this);
    }
    StrBlob_ptr StrBlob::end() const
    {
        return StrBlob_ptr(*this, data->size());
    }
    
    /******************************************************************************************************************/
    
    class ResultQuery
    {
        friend ostream &print(ostream &, const ResultQuery &);
    
    public:
        // 单词
        string w;
        // 行号的列表
        shared_ptr<set<int>> lines;
        // 全部的文本,可以通过行号寻找
        shared_ptr<StrBlob> txtline; //----------modify
    
    public:
        ResultQuery(string word, shared_ptr<set<int>> line_num, shared_ptr<StrBlob> txt) : w(word), lines(line_num), txtline(txt){}; //----------modify
        ~ResultQuery(){};
    };
    
    class TextQuery
    {
    private:
        /* data */
        shared_ptr<StrBlob> txtline; //----------modify
        // 因为在ret里面共享的是set的行号,所以这里也是行号共享指针,而不是整个map
        map<string, shared_ptr<set<int>>> data;
    
    public:
        TextQuery(ifstream &file);
        ResultQuery Query(string &w);
        ~TextQuery(){};
    };
    
    TextQuery::TextQuery(ifstream &file) : txtline(new StrBlob) //----------modify
    {
        // 读入文件到文件流,保存每一行到vector<string>
        string s;
        int line_at = 0;
        while (getline(file, s))
        {
            txtline->push_back(s); //----------modify
            string ch;
            istringstream ss(s);
            while (ss >> ch)
            {
                if (!data[ch])
                    data[ch].reset(new set<int>);
                data[ch]->insert(line_at);
            }
            line_at++;
        }
    }
    
    ResultQuery TextQuery::Query(string &w)
    {
        static shared_ptr<std::set<int>> nodate(new std::set<int>);
        auto found = data.find(w);
        if (found == data.end())
            return ResultQuery(w, nodate, txtline);
        else
            return ResultQuery(w, data[w], txtline);
    }
    //ostream &print(ostream &, const ResultQuery &)
    ostream &print(ostream &out, const ResultQuery &want)
    {
        out << "----------------------------------------------" << endl;
        out << "string:" << want.w << endl;
        out << "Txt List:" << endl;
        //if (want.lines) // 先要判断指针是否存在
        {
            for (auto ls : *(want.lines))
            {
                StrBlob_ptr xx(*(want.txtline), ls);          //----------modify
                out << ls << ":			" << xx.deref() << endl; //----------modify
            }
    
            //qr.input->at(i)
        }
    
        out << "----------------------------------------------" << endl;
        return out;
    }
    
    void runQueries(ifstream &file)
    {
        // 从文件流建立查询的数据
        TextQuery tq(file);
        while (true)
        {
            cout << "Enter what you want to find?" << endl;
            string s;
            if (!(cin >> s) || s == "q")
                break;
            print(cout, tq.Query(s)) << endl;
        }
    }
    
    int main(int argc, char const *argv[])
    {
        ifstream fs("D:\a.txt");
        if (fs)
            runQueries(fs);
        else
            cout << "fs open failed " << endl;
    
        while (1)
            ;
        return 0;
    }
    
    

    12.33

    /*
    
    12.33 增加 QueryResult 的begin,end 取得set的begin,end  增加一个get_file  返回shared_ptr 指向QueryResult的文件也就是strBlob_ptr
    
    12.32
    重写TextQuery和QueryResult类,用StrBlob代替vector<vector>保存输入文件
    
    TextQuery 使用StrBlob  存储shared_ptr<vector<string>>  文本
    具体查询打印的时候,我们要从 *(StrBlob.ptr) 中取小标
    也就是 使用 StrBlob_ptr 这个类指向了StrBlob中vector[下标]
    
    github的答案是这里 使用 shared_ptr 执行StrBlob 也就是  shared_ptr<StrBlob> 的操作,
    */
    
    /*
    12.19 
    12.20 读入文件 使用这个类
    12.22 使用  const StrBlob类
    			strBlob begin end 返回const
                底层指针是个const,只有在构造的时候赋值
                解引用的时候返回const  
    
    一个 StrBlob类,底层数据是指向 vector<string> 的指针
    一个 StrBlob_ptr类,可以认为是StrBlob类的指针类
    
    定义  StrBlob类,数据成员是 vector<string> 的shared_ptr
            begin  指向第一个元素的 StrBlob_ptr 也就是cur=0?
            end                   最后一个元素的指针cur=size()   end是开区间,所以不用减1
    定义  StrBlob_ptr 类,指向 StrBlob类中的数据成员 *shared_ptr
            一个指向 vector<string> 的指针,带有小标
            *      获得string
            ++     将下标++
    
    
    */
    
    #include <vector>
    #include <string>
    #include <memory>
    #include <initializer_list>
    #include <exception>
    #include <iostream>
    #include <fstream>
    #include <set>
    #include <map>
    #include <sstream>
    
    using namespace std;
    
    class StrBlob_ptr;
    
    class StrBlob
    {
        using Blob_size_type = vector<string>::size_type;
    
        friend class StrBlob_ptr;
    
    private:
        /* data */
        shared_ptr<vector<string>> data;
    
    public:
        StrBlob() : data(make_shared<vector<string>>()) {}
        StrBlob(initializer_list<string> li) : data(make_shared<vector<string>>(li)) {}
    
        StrBlob_ptr begin() const; //{ return StrBlob_ptr(*this); }
        StrBlob_ptr end() const;   //{ return StrBlob_ptr(*this, data->size()); }
    
        Blob_size_type size() const
        {
            return data->size();
        }
    
        bool empty() const
        {
            return data->empty();
        }
    
        bool check(Blob_size_type has, const string &msg) const
        {
            if (has >= data->size())
                throw std::out_of_range(msg);
        }
    
        void push_back(string &s)
        {
            data->push_back(s);
        }
        void pop_back()
        {
            check(0, "pop_back");
            data->pop_back();
        }
    
        string &front()
        {
            check(0, "front");
            return data->front();
        }
    
        string &back()
        {
            check(0, "back");
            return data->back();
        }
    
        const string &front() const
        {
            check(0, "front");
            return data->front();
        }
    
        const string &back() const
        {
            check(0, "back");
            return data->back();
        }
    
        ~StrBlob() {}
    };
    
    class StrBlob_ptr
    {
    private:
        // 底层指针指向的内容是 shared_ptr,可能存在释放的情况
        weak_ptr<vector<string>> ptr;
        int cur;
        shared_ptr<vector<string>> check(int size, const string msg) const;
    
    public:
        // 构造函数,指向空的ptr
        StrBlob_ptr() : cur(0) {}
        StrBlob_ptr(const StrBlob &s, int offset = 0) : ptr(s.data), cur(offset) {}
        ~StrBlob_ptr() {}
    
        // * 解引用
        const string &deref() const;
        StrBlob_ptr &increase_ref();
        // 同时需要定义!= 这里应该还要判断 p的指向是否相同
        bool operator!=(const StrBlob_ptr &p) { return p.cur != cur; }
    };
    
    shared_ptr<vector<string>> StrBlob_ptr::check(int size, const string msg) const
    {
        auto ptr_get = ptr.lock();
        if (!ptr_get)
            throw runtime_error(msg);
        if (size >= ptr_get->size())
            throw out_of_range(msg);
        return ptr_get;
    }
    
    const string &StrBlob_ptr::deref() const
    {
        auto ptr_get = check(cur, "get shared_ptr");
        return (*ptr_get)[cur];
    }
    
    StrBlob_ptr &StrBlob_ptr::increase_ref()
    {
        check(cur, "get shared_ptr");
        cur++;
        return *this;
    }
    
    /*
     *   这两个函数一定要放到 StrBlob_ptr 这个类下面定义,因为用到了StrBlob_ptr具体的构造函数; 即使最开始已经声明了
     *    
     *
     *
    */
    StrBlob_ptr StrBlob::begin() const
    {
        return StrBlob_ptr(*this);
    }
    StrBlob_ptr StrBlob::end() const
    {
        return StrBlob_ptr(*this, data->size());
    }
    
    /******************************************************************************************************************/
    
    class ResultQuery
    {
        friend ostream &print(ostream &, const ResultQuery &);
    
    public:
        // 单词
        string w;
        // 行号的列表
        shared_ptr<set<int>> lines;
        // 全部的文本,可以通过行号寻找
        StrBlob txtline; //----------modify
    
    public:
        ResultQuery(string word, shared_ptr<set<int>> line_num, StrBlob txt) : w(word), lines(line_num), txtline(txt){}; //----------modify
    
        set<int>::iterator begin() const { return lines->begin(); } // 这里要使用const 因为下面的调用是使用  const ResultQuery&
        set<int>::iterator end() const { return lines->end(); }
        StrBlob get_file() { return txtline; }
    
        ~ResultQuery(){};
    };
    
    class TextQuery
    {
    private:
        /* data */
        StrBlob txtline; //----------modify
        // 因为在ret里面共享的是set的行号,所以这里也是行号共享指针,而不是整个map
        map<string, shared_ptr<set<int>>> data;
    
    public:
        TextQuery(ifstream &file);
        ResultQuery Query(string &w);
        ~TextQuery(){};
    };
    
    TextQuery::TextQuery(ifstream &file) : txtline() //----------modify
    {
        // 读入文件到文件流,保存每一行到vector<string>
        string s;
        int line_at = 0;
        while (getline(file, s))
        {
            txtline.push_back(s); //----------modify
            string ch;
            istringstream ss(s);
            while (ss >> ch)
            {
                if (!data[ch])
                    data[ch].reset(new set<int>);
                data[ch]->insert(line_at);
            }
            line_at++;
        }
    }
    
    ResultQuery TextQuery::Query(string &w)
    {
        static shared_ptr<std::set<int>> nodate(new std::set<int>);
        auto found = data.find(w);
        if (found == data.end())
            return ResultQuery(w, nodate, txtline);
        else
            return ResultQuery(w, data[w], txtline);
    }
    //ostream &print(ostream &, const ResultQuery &)
    ostream &print(ostream &out, const ResultQuery &want)
    {
        out << "----------------------------------------------" << endl;
        out << "string:" << want.w << endl;
        out << "Txt List:" << endl;
    
        for (auto it = want.begin(); it != want.end(); it++)
        {
            StrBlob_ptr xx(want.txtline, *it);             //----------modify
            out << *it << ":			" << xx.deref() << endl; //----------modify
        }
    
        //for(auto it=want.begin();)
        //if (want.lines) // 先要判断指针是否存在
        {
            // for (auto ls : *(want.lines))
            // {
            //     StrBlob_ptr xx(want.txtline, ls);             //----------modify
            //     out << ls << ":			" << xx.deref() << endl; //----------modify
            // }
    
            //qr.input->at(i)
        }
    
        out << "----------------------------------------------" << endl;
        return out;
    }
    
    void runQueries(ifstream &file)
    {
        // 从文件流建立查询的数据
        TextQuery tq(file);
        while (true)
        {
            cout << "Enter what you want to find?" << endl;
            string s;
            if (!(cin >> s) || s == "q")
                break;
            print(cout, tq.Query(s)) << endl;
        }
    }
    
    int main(int argc, char const *argv[])
    {
        ifstream fs("D:\a.txt");
        if (fs)
            runQueries(fs);
        else
            cout << "fs open failed " << endl;
    
        while (1)
            ;
        return 0;
    }
    
    

    12.33.2

    /*
    
    12.33.2 
    完全使用 shared_ptr<StrBlob>  替换  shared_ptr<vector<string>>
    
    12.33 增加 QueryResult 的begin,end 取得set的begin,end  增加一个get_file  返回shared_ptr 指向QueryResult的文件也就是strBlob_ptr
    
    12.32
    重写TextQuery和QueryResult类,用StrBlob代替vector<vector>保存输入文件
    
    TextQuery 使用StrBlob  存储shared_ptr<vector<string>>  文本
    具体查询打印的时候,我们要从 *(StrBlob.ptr) 中取小标
    也就是 使用 StrBlob_ptr 这个类指向了StrBlob中vector[下标]
    
    github的答案是这里 使用 shared_ptr 执行StrBlob 也就是  shared_ptr<StrBlob> 的操作,
    */
    
    /*
    12.19 
    12.20 读入文件 使用这个类
    12.22 使用  const StrBlob类
    			strBlob begin end 返回const
                底层指针是个const,只有在构造的时候赋值
                解引用的时候返回const  
    
    一个 StrBlob类,底层数据是指向 vector<string> 的指针
    一个 StrBlob_ptr类,可以认为是StrBlob类的指针类
    
    定义  StrBlob类,数据成员是 vector<string> 的shared_ptr
            begin  指向第一个元素的 StrBlob_ptr 也就是cur=0?
            end                   最后一个元素的指针cur=size()   end是开区间,所以不用减1
    定义  StrBlob_ptr 类,指向 StrBlob类中的数据成员 *shared_ptr
            一个指向 vector<string> 的指针,带有小标
            *      获得string
            ++     将下标++
    
    
    */
    
    #include <vector>
    #include <string>
    #include <memory>
    #include <initializer_list>
    #include <exception>
    #include <iostream>
    #include <fstream>
    #include <set>
    #include <map>
    #include <sstream>
    
    using namespace std;
    
    class StrBlob_ptr;
    
    class StrBlob
    {
        using Blob_size_type = vector<string>::size_type;
    
        friend class StrBlob_ptr;
    
    private:
        /* data */
        shared_ptr<vector<string>> data;
    
    public:
        StrBlob() : data(make_shared<vector<string>>()) {}
        StrBlob(initializer_list<string> li) : data(make_shared<vector<string>>(li)) {}
    
        StrBlob_ptr begin() const; //{ return StrBlob_ptr(*this); }
        StrBlob_ptr end() const;   //{ return StrBlob_ptr(*this, data->size()); }
    
        Blob_size_type size() const
        {
            return data->size();
        }
    
        bool empty() const
        {
            return data->empty();
        }
    
        bool check(Blob_size_type has, const string &msg) const
        {
            if (has >= data->size())
                throw std::out_of_range(msg);
        }
    
        void push_back(string &s)
        {
            data->push_back(s);
        }
        void pop_back()
        {
            check(0, "pop_back");
            data->pop_back();
        }
    
        string &front()
        {
            check(0, "front");
            return data->front();
        }
    
        string &back()
        {
            check(0, "back");
            return data->back();
        }
    
        const string &front() const
        {
            check(0, "front");
            return data->front();
        }
    
        const string &back() const
        {
            check(0, "back");
            return data->back();
        }
    
        ~StrBlob() {}
    };
    
    class StrBlob_ptr
    {
    private:
        // 底层指针指向的内容是 shared_ptr,可能存在释放的情况
        weak_ptr<vector<string>> ptr;
        int cur;
        shared_ptr<vector<string>> check(int size, const string msg) const;
    
    public:
        // 构造函数,指向空的ptr
        StrBlob_ptr() : cur(0) {}
        StrBlob_ptr(const StrBlob &s, int offset = 0) : ptr(s.data), cur(offset) {}
        ~StrBlob_ptr() {}
    
        // * 解引用
        const string &deref() const;
        StrBlob_ptr &increase_ref();
        // 同时需要定义!= 这里应该还要判断 p的指向是否相同
        bool operator!=(const StrBlob_ptr &p) { return p.cur != cur; }
    };
    
    shared_ptr<vector<string>> StrBlob_ptr::check(int size, const string msg) const
    {
        auto ptr_get = ptr.lock();
        if (!ptr_get)
            throw runtime_error(msg);
        if (size >= ptr_get->size())
            throw out_of_range(msg);
        return ptr_get;
    }
    
    const string &StrBlob_ptr::deref() const
    {
        auto ptr_get = check(cur, "get shared_ptr");
        return (*ptr_get)[cur];
    }
    
    StrBlob_ptr &StrBlob_ptr::increase_ref()
    {
        check(cur, "get shared_ptr");
        cur++;
        return *this;
    }
    
    /*
     *   这两个函数一定要放到 StrBlob_ptr 这个类下面定义,因为用到了StrBlob_ptr具体的构造函数; 即使最开始已经声明了
     *    
     *
     *
    */
    StrBlob_ptr StrBlob::begin() const
    {
        return StrBlob_ptr(*this);
    }
    StrBlob_ptr StrBlob::end() const
    {
        return StrBlob_ptr(*this, data->size());
    }
    
    /******************************************************************************************************************/
    
    class ResultQuery
    {
        friend ostream &print(ostream &, const ResultQuery &);
    
    public:
        // 单词
        string w;
        // 行号的列表
        shared_ptr<set<int>> lines;
        // 全部的文本,可以通过行号寻找
        shared_ptr<StrBlob> txtline; //----------modify
    
    public:
        ResultQuery(string word, shared_ptr<set<int>> line_num, shared_ptr<StrBlob> txt) : w(word), lines(line_num), txtline(txt){}; //----------modify
    
        set<int>::iterator begin() const { return lines->begin(); } // 这里要使用const 因为下面的调用是使用  const ResultQuery&
        set<int>::iterator end() const { return lines->end(); }
        shared_ptr<StrBlob> get_file() const { return txtline; } //modify
    
        ~ResultQuery(){};
    };
    
    class TextQuery
    {
    private:
        /* data */
        shared_ptr<StrBlob> txtline; //----------modify
        // 因为在ret里面共享的是set的行号,所以这里也是行号共享指针,而不是整个map
        map<string, shared_ptr<set<int>>> data;
    
    public:
        TextQuery(ifstream &file);
        ResultQuery Query(string &w);
        ~TextQuery(){};
    };
    
    TextQuery::TextQuery(ifstream &file) : txtline(new StrBlob) //----------modify
    {
        // 读入文件到文件流,保存每一行到vector<string>
        string s;
        int line_at = 0;
        while (getline(file, s))
        {
            txtline->push_back(s); //----------modify
            string ch;
            istringstream ss(s);
            while (ss >> ch)
            {
                if (!data[ch])
                    data[ch].reset(new set<int>);
                data[ch]->insert(line_at);
            }
            line_at++;
        }
    }
    
    ResultQuery TextQuery::Query(string &w)
    {
        static shared_ptr<std::set<int>> nodate(new std::set<int>);
        auto found = data.find(w);
        if (found == data.end())
            return ResultQuery(w, nodate, txtline);
        else
            return ResultQuery(w, data[w], txtline);
    }
    //ostream &print(ostream &, const ResultQuery &)
    ostream &print(ostream &out, const ResultQuery &want)
    {
        out << "----------------------------------------------" << endl;
        out << "string:" << want.w << endl;
        out << "Txt List:" << endl;
    
        for (auto it = want.begin(); it != want.end(); it++)
        {
            StrBlob_ptr xx(*(want.get_file()), *it);
            //StrBlob_ptr xx(*(want.txtline), *it);          //----------modify
            out << *it << ":			" << xx.deref() << endl; //----------modify
        }
    
        //for(auto it=want.begin();)
        //if (want.lines) // 先要判断指针是否存在
        {
            // for (auto ls : *(want.lines))
            // {
            //     StrBlob_ptr xx(want.txtline, ls);             //----------modify
            //     out << ls << ":			" << xx.deref() << endl; //----------modify
            // }
    
            //qr.input->at(i)
        }
    
        out << "----------------------------------------------" << endl;
        return out;
    }
    
    void runQueries(ifstream &file)
    {
        // 从文件流建立查询的数据
        TextQuery tq(file);
        while (true)
        {
            cout << "Enter what you want to find?" << endl;
            string s;
            if (!(cin >> s) || s == "q")
                break;
            print(cout, tq.Query(s)) << endl;
        }
    }
    
    int main(int argc, char const *argv[])
    {
        ifstream fs("D:\a.txt");
        if (fs)
            runQueries(fs);
        else
            cout << "fs open failed " << endl;
    
        while (1)
            ;
        return 0;
    }
    
    
  • 相关阅读:
    element-ui 和ivew-ui的table导出export纯前端(可用)
    webstrom 2019 注册码(可用 2019年10月14日08:59:18)
    intellji IDEA 2019版激活码(亲测可用 2019年10月14日08:53:54)
    java开发相关工具安装包分享
    js有关字符串拼接问题
    js增删class的方法
    有关定位问题
    关于网页元素居中常见的两种方法
    有关css编写文字动态下划线
    js获取时间及转化
  • 原文地址:https://www.cnblogs.com/zongzi10010/p/12490782.html
Copyright © 2020-2023  润新知