// StrBlob类的定义.h文件
#ifndef STRBLOB_H
#define STRBLOB_H
#include<vector>
#include<string>
#include<initializer_list>
#include<memory>
using namespace::std;
class StrBlob
{
friend class QueryResultStrBlob;
public:
typedef vector<string>::size_type size_type;
StrBlob();
StrBlob(initializer_list<string>il);
StrBlob(const StrBlob&); //拷贝构造
size_type size() const { return data->size(); }
bool empty() const { return data->empty(); }
//添加和删除元素
void push_back(const string& t) { data->push_back(t); }
void pop_back();
//元素访问
string& front();
string& back();
const string& front() const;
const string& back() const;
const string& backi(size_type i) const;
private:
shared_ptr<vector<string>>data;
void check(size_type i, const string& msg) const;
};
//StrBlob类的实现.cpp文件
#include "StrBlob.h"
StrBlob::StrBlob():data(make_shared<vector<string>>()) { }
StrBlob::StrBlob(initializer_list<string>il) : data(make_shared<vector<string>>(il)) { }
StrBlob::StrBlob(const StrBlob& strb) //拷贝构造,输入一定是常量类的引用
{
data = strb.data;
}
void StrBlob::check(size_type i, const string& msg) const
{
if (i >= msg.size())
throw out_of_range(msg);
}
void StrBlob::pop_back()
{
check(0, "pop_back on empty StrBlob");
data->pop_back();
}
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 //后面的const表示不能修改this指针,前面的const表示返回类型是const
{
check(0, "back on empty StrBlob");
return data->back();
}
const string& StrBlob::backi(size_type i) const
{
check(0, "return element on empty StrBlob");
return *(data->begin() + i);
}
// TextQueryStrBlob,QueryResultStrBlob类的定义.h文件
#ifndef TEXTQUERYSTRBLOB_H
#define TEXTQUERYSTRBLOB_H
#include<memory>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<fstream>
#include<sstream>
#include "StrBlob.h"
class QueryResultStrBlob;
class TextQueryStrBlob
{
public:
using line_no = std::vector<std::string>::size_type;
TextQueryStrBlob(std::ifstream&);
QueryResultStrBlob query(const std::string&) const;
private:
StrBlob file; //输入文件,里面的智能指针指向一个空的vector<string>
std::map<std::string, std::shared_ptr<std::set<line_no>>> wm;//每个单词到到它所在行号的集合的映射
};
class QueryResultStrBlob
{
friend std::ostream& print(std::ostream&, const QueryResultStrBlob&);
public:
using line_no = std::vector<std::string>::size_type;
QueryResultStrBlob(std::string s,
std::shared_ptr<std::set<line_no>> p,const StrBlob& f) :
sought(s),lines(p),file(f) { }
private:
std::string sought; //查询单词
std::shared_ptr<std::set<line_no>> lines; //出现的行号
StrBlob file; //输入的文件
};
#endif;
// TextQueryStrBlob,QueryResultStrBlob类的实现.cpp文件
#include "TextQueryStrBlob.h"
using namespace::std;
TextQueryStrBlob::TextQueryStrBlob(ifstream& infile)
{ string str;
while (getline(infile, str))
{
file.push_back(str);
int num = file.size() - 1; //当前行号
istringstream istr(str);
string word;
while (istr >> word)
{
auto &line = wm[word]; //line为行号的set的指针,如果word是第一次出现,则先添加word后绑定,否则直接line和指针绑定
if (!line) //如果指向的是空对象,说明此word还没有创建新的set,要创建新的set,为后续插入行号做准备
line.reset(new set<line_no>);//重新分配对象给line
line->insert(num); //如果一个单词在一行中出现多次,则只记录一次
}
}
}
QueryResultStrBlob TextQueryStrBlob::query(const string& word) const
{//查询单词,把结果传给QueryResult
auto ret = wm.find(word);
if (ret != wm.end())
return QueryResultStrBlob(word, ret->second,file);
else
{
static shared_ptr<set<line_no>> p(new set<line_no>);
return QueryResultStrBlob(word, p,file);
}
}
string make_plural(size_t ctr, const string &word, const string &ending)
{
return(ctr > 1) ? word + ending : word;
}
ostream &print(ostream& out, const QueryResultStrBlob& qr)
{
out << qr.sought << " occurs " << qr.lines->size() << make_plural(qr.lines->size(), "times", "s") << endl;
for (auto wq = qr.lines->begin(); wq != qr.lines->end(); ++wq)
{
out << "(line " << *wq + 1 << ")" << qr.file.backi(*wq)<< endl;
}
return out;
}
//测试文件.cpp
#include<iostream>
#include "TextQueryStrBlob.h"
using namespace std;
void RunQueriesStrBlob(ifstream &infile)
{
TextQueryStrBlob tq(infile);
while (true)
{
cout << "enter word to look for,or q to quit: ";
string s;
if (!(cin >> s) || s == "q") break;
print(cout, tq.query(s)) << endl;
}
}
int main()
{
ifstream infile("wordtext.txt");
RunQueriesStrBlob(infile);
return 0;
}
输入文件:
输出结果: