文本查询-My(StrVec提供类间共享元素的能力!)

// 文本查询程序-My.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
#include<fstream>
#include<sstream>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<memory>
#include<initializer_list>

using namespace std;

class StrVec
{
    using size_type = vector<string>::size_type;
public:
    StrVec():data(new vector<string>()){}       //默认初始化!
    StrVec(initializer_list<string> il):data(make_shared<vector<string>>(il)) {} //il就这么用!

    //StrVec(const StrVec &rh):data(copy_shared(rh)){}智能指针与拷贝构造函数、拷贝赋值、移动构造函数、移动赋值的使用样本?》
    ~StrVec()=default;

    void push_back(const string &s);
    void pop_back();

    size_type size()const { return data->size(); }
    bool empty()const { return data->empty(); }

    string &front();
    string &back();
    string& operator[] (const size_type &i);
    string& operator[] (const size_type &i) const;

    explicit operator bool()const { return data->size() > 0 ? true : false; }

private:
    shared_ptr<vector<string>> data;
    void check(unsigned i)      //检查data[i]是否越界?
    {
        if (i >= data->size())
            throw out_of_range("Out_of_range!");
    }
    shared_ptr<vector<string>> copy_shared(const StrVec &rh)
    {
        shared_ptr<vector<string>> ret;
        auto beg = ret->begin();
        uninitialized_copy(rh.data->cbegin(), rh.data->cend(), beg++);
        return ret;
    }
};

void StrVec::push_back(const string &s)
{
    data->push_back(s);
}
void StrVec::pop_back()
{
    check(0);
    data->pop_back();
}
string& StrVec::front()
{
    check(0);
    return data->at(0);
}
string& StrVec::back()
{
    check(0);
    return data->at(data->size()-1);
}
string& StrVec::operator[](const size_type &i)
{
    check(i);
    return data->at(i);
}
string& StrVec::operator[] (const size_type &i) const   //区分StrVec本身,const版本和非const版本!
{
    //check(i);             //check暂时没有定义const版本,故在此舍弃!
    return data->at(i);
}


class QueryR
{
public:
    QueryR(const string &s, shared_ptr<map<string, set<unsigned>>> l, StrVec f) :word(s), linenu(l), file(f) {}
    ~QueryR() = default;

    friend ostream& operator<<(ostream &os, QueryR rh);
private:
    string word;
    shared_ptr<map<string, set<unsigned>>> linenu;
    StrVec file;
};
ostream& operator<<(ostream &os, QueryR rh)
{
    os << rh.word <<" occurs " << rh.linenu->at(rh.word).size() << " times" << endl;
    for (auto &r : rh.linenu->at(rh.word))
    {
        os << "\t(line " << r+1 << ")" << rh.file[r]<<endl;//       const QueryR,其file不能使用[]???
    }
    return os;
}

class Text
{
public:
    Text(const string &filename):linenu(make_shared<map<string,set<unsigned>>>()) { read(filename); }
    ~Text()=default;

    QueryR query(const string &s);

private:
    shared_ptr<map<string, set<unsigned>>> linenu;      //要么在构造函数中绑定,要么在函数中绑定内存!
    StrVec file;                                        //由类自己决定
    void read(const string &filename);
};

void Text::read(const string &filename)
{
    ifstream f(filename);
    if (f)
    {
        string tmp;
        unsigned row = 0;                       //单词所在的行号
        while (getline(f,tmp))
        {
            istringstream line(tmp);
            string word;
            while (line>>word)
            {
                if(linenu->find(word)==linenu->cend())
                    (*linenu)[word];            //如果不存在,则创建pair<string,set<unsigned>>
                (*linenu)[word].insert(row);    //单词word,插入行号row
            }
            file.push_back(tmp);                //保存每一行的tmp
            row = row + 1;
        }
    }
    f.close();
}

QueryR Text::query(const string &s)
{
    if (linenu->find(s) != linenu->cend())
        return QueryR(s, linenu, file);
    else
        return QueryR(s, nullptr, file);
}




int main()
{
    string filename = "C:\\Users\\winack\\Documents\\Visual Studio 2017\\Projects\\文本查询程序-My\\123.txt";
    Text info(filename);
    cout << info.query("is");

    StrVec sv;
    sv.push_back("asdfg");
    const StrVec &ssv = sv;
    cout <<"非const版本: "<<sv[0]<<" && "<<"是const版本: "<< ssv[0] << endl;

    return 0;
}

推荐阅读更多精彩内容