文本查询-My(StrVec提供类间共享元素的能力!)
2017-09-10 本文已影响0人
峡迩
// 文本查询程序-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;
}