首先准备一个.txt文件做查询使用。例如下(准备英文即可,中文暂不支持):
要实现的功能如下:
1、查询单个单词
2、查询单个单词的非
3、查询两个单词的并集
4、查询两个单词的交集
由题目观察可知,我们应该将几种不同的查询建模成相互独立的类,这些类共享一个公共基类。
这些类将只包含两个操作:
eval:接受一个TextQuery对象并返回一个QueryResult,eval函数使用给定的TextQuery对象查找与之匹配的行。
rep:返回基础查询的string表示形式,eval函数使用rep创建一个表示匹配结果的QueryResult,输出运算符使用rep打印查询表达式。
Query_base 继承体系设计如下:
在程序中我们还将定义一个Query的接口类,由它负责隐藏整个继承体系。
Query类将保存一个Query_base指针,该指针绑定到Query_base的派生类对象上。这样Query类与Query_base类提供的操作是相同的:eval用于求查询结果,rep用于生成查询的string结果,同时Query 也会定义一个重载的输出运算符用于显示查询。
设计类图如下:
github 地址:https://github.com/HSbear/TextSearch
实现代码:
#include <iostream>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <fstream>
#include <sstream>
#include <memory>
#include<algorithm>
using namespace std;
class QueryResult;
class TextQuery
{
public:
using line_no = vector<string>::size_type;
TextQuery(ifstream&);
QueryResult query(const string&)const;
private:
shared_ptr<vector<string>> file; //输入文件
map<string,shared_ptr<set<line_no>>> wordmap;
};
class QueryResult {
friend ostream &print(ostream &,const QueryResult &);
public:
QueryResult(string s,
shared_ptr<set<TextQuery::line_no>> p,
shared_ptr<vector<string>> f)
: sought(s)
, lines(p)
, file(f)
{
}
set<TextQuery::line_no>::iterator begin() {
return lines->begin(); }
set<TextQuery::line_no>::iterator end() {
return lines->end(); }
shared_ptr<vector<string>> get_file() {
return file; }
private:
string sought;
shared_ptr<set<TextQuery::line_no>> lines;
shared_ptr<vector<string>> file;
};
TextQuery::TextQuery(ifstream &is)
: file(new vector<string>)
{
string text;
while(getline(is,text)){
file->push_back(text);
int n=file->size() - 1;
istringstream line(text);
string word;
while(line >> word)
{
auto &lines = wordmap[word];
if(!lines)
lines.reset(new set<line_no>);
lines->insert(n);
}
}
}
QueryResult TextQuery::query(const string& sought) const
{
//如果未找到sought,则返回一个指向此set的指针
static shared_ptr<set