文本查询
支持功能
- 单词查询
- 逻辑非查询
- 逻辑或查询
- 逻辑与查询
- 以及混合查询
查询子系统类图
门面类Query
隐藏查询系统,提供对外查询接口
#ifndef _QUERY_H_
#define _QUERY_H_
#include <memory>
#include "TextQuery.h"
#include "WordQuery.h"
class Query_base;
class Query {
friend Query operator~(const Query&);
friend Query operator|(const Query&, const Query&);
friend Query operator&(const Query&, const Query&);
public:
Query(const std::string& s): q(new WordQuery(s)) {
if(q->isDeBug) std::cout << "Query::Query(const std::string& s) where s="+s+"\n";
}
QueryResult eval(const TextQuery &t) const {
if(q->isDeBug) std::cout << "Query::eval()\n";
return q->eval(t);
}
std::string rep() const {
if(q->isDeBug) std::cout << "Query::rep()\n";
return q->rep();
}
void setDebug(bool b) {
q->isDeBug = b;
}
bool getDebug() {
return q->isDeBug;
}
private:
Query(std::shared_ptr<Query_base> query): q(query) {
std::cout << "Query::Query(std::shared_ptr<Query_base> query)\n";
}
std::shared_ptr<Query_base> q;
};
#endif
Query_base抽象类
#ifndef _QUERY_BASE_H_
#define _QUERY_BASE_H_
#include "TextQuery.h"
class Query_base {
friend class Query;
protected:
virtual ~Query_base() = default;
static bool isDeBug;
private:
//查询结果函数
virtual QueryResult eval(const TextQuery&) const = 0;
//返回基础查询的string表示形式
virtual std::string rep() const = 0;
public:
void setDebug(bool b) { isDeBug = b;}
bool getDebug() { return isDeBug;}
};
bool Query_base::isDeBug = true;
#endif // _QUERY_BASE_H_
二元操作BinaryQuery抽象类
#ifndef _BINARY_H_
#define _BINARY_H_
#include "Query.h"
#include "Query_base.h"
class BinaryQuery: public Query_base {
protected:
BinaryQuery(const Query &l, const Query &r, std::string s):
lhs(l), rhs(r), opSym(s)
{
if(isDeBug) std::cout << "BinaryQuery::BinaryQuery() where s=" + s + "\n";
}
std::string rep() const {
if(isDeBug) std::cout << "BinaryQuery::rep()\n";
return "(" + lhs.rep() + " "+ opSym + " "+ rhs.rep() + ")";
}
Query lhs, rhs;
std::string opSym;
};
#endif
逻辑与AndQuery类
#ifndef _AND_H_
#define _AND_H_
#include "BinaryQuery.h"
#include <algorithm>
class AndQuery: public BinaryQuery {
friend Query operator&(const Query&, const Query&);
AndQuery(const Query &left, const Query &right): BinaryQuery(left, right, "&") {
if(isDeBug) std::cout << "AndQuery::AndQuery()\n";
}
QueryResult eval(const TextQuery&) const ;
};
inline Query operator&(const Query &lhs, const Query &rhs) {
return std::shared_ptr<Query_base>(new AndQuery(lhs, rhs));
}
QueryResult AndQuery::eval(const TextQuery& text) const {
if(isDeBug) std::cout << "AndQuery::eval()\n";
auto right = rhs.eval(text), left = lhs.eval(text);
//and,求两个结果的并集
auto ret_lines = make_shared<set<line_no>>();
std::set_intersection(left.begin(), left.end(),
right.begin(), right.end(),
inserter(*ret_lines, ret_lines->begin()));
return QueryResult(rep(), ret_lines, left.get_file());
}
#endif
逻辑或OrQuery类
#ifndef _OR_H_
#define _OR_H_
#include "BinaryQuery.h"
#include "Query.h"
class OrQuery: public BinaryQuery {
friend Query operator|(const Query&, const Query&);
OrQuery(const Query &left, const Query &right): BinaryQuery(left, right, "|") {
if(isDeBug) std::cout << "OrQuery::OrQuery\n";
}
QueryResult eval(const TextQuery&) const;
};
inline Query operator|(const Query &lhs, const Query &rhs) {
return std::shared_ptr<Query_base>(new OrQuery(lhs, rhs));
}
QueryResult OrQuery::eval(const TextQuery& text) const {
if(isDeBug) std::cout << "OrQuery::eval()\n";
//查询左右两边的对象的结果
auto right = rhs.eval(text), left = lhs.eval(text);
//or,将讲个结果合成一个
auto ret_lines = make_shared<set<line_no>>(left.begin(), left.end());
ret_lines->insert(right.begin(), right.end());
return QueryResult(rep(), ret_lines, left.get_file());
}
#endif
逻辑非NotQuery类
#ifndef _NOT_H_
#define _NOT_H_
#include "Query.h"
#include "Query_base.h"
class NotQuery: public Query_base {
friend Query operator~(const Query &);
NotQuery(const Query &q): query(q) {
if(isDeBug) std::cout << "NotQuery::NotQuery()\n";
}
std::string rep() const {
if(isDeBug) std::cout << "NotQuery::rep()\n";
return "~(" + query.rep() + ")";
}
QueryResult eval(const TextQuery&) const ;
Query query;
};
inline Query operator~(const Query &operand) {
return std::shared_ptr<Query_base>(new NotQuery(operand));
}
QueryResult NotQuery::eval(const TextQuery& text) const {
if(isDeBug) std::cout << "NotQuery::eval()\n";
auto result = query.eval(text);
auto ret_lines = make_shared<set<line_no>>();
auto beg = result.begin(), end = result.end();
auto sz = result.get_file()->size();
for(size_t n = 0; n != sz; ++n) {
if(beg == end || *beg != n)
ret_lines->insert(n);
else if(beg != end)
++beg;
}
return QueryResult(rep(), ret_lines, result.get_file());
}
#endif
单字符串查询WordQuery类
#ifndef _WORDQUERY_H_
#define _WORDQUERY_H_
#include "Query_base.h"
class WordQuery: public Query_base {
friend class Query;
WordQuery(const std::string &s): query_word(s) {
if(isDeBug)std::cout << "WordQuery::WordQuery(" + s + ")\n";
}
QueryResult eval(const TextQuery &t) const {
if(isDeBug)std::cout << "WordQuery::eval()\n";
return t.query(query_word);
}
std::string rep() const {
if(isDeBug)std::cout << "WordQuery::rep()\n";
return query_word;
}
std::string query_word;
};
#endif
查询类TextQuery
#ifndef _TEXTQUERY_H_
#define _TEXTQUERY_H_
#include "QueryResult.h"
class QueryResult;
class TextQuery {
public:
TextQuery(ifstream&);
QueryResult query(const string &) const;
private:
shared_ptr<vector<string>> file;
map<string, shared_ptr<set<line_no>>> wm;
};
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 = wm[word];
if(!lines)
lines.reset(new set<line_no>);
lines->insert(n);
}
}
}
QueryResult TextQuery::query(const string &sought) const {
static shared_ptr<set<line_no>> nodata(new set<line_no>);
auto loc = wm.find(sought);
if(loc == wm.end())
return QueryResult(sought, nodata, file);
else
return QueryResult(sought, loc->second, file);
}
#endif // _TEXTQUERY_H_
查询结果类
#ifndef _QUERYRESULT_H_
#define _QUERYRESULT_H_
#include <fstream>
#include <sstream>
#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <map>
#include <set>
using namespace std;
typedef vector<string>::size_type line_no;
class QueryResult {
friend std::ostream& print(std::ostream&, const QueryResult&);
public:
QueryResult(string s, shared_ptr<set<line_no>> p,
shared_ptr<vector<string>> f):
sought(s), lines(p), file(f){ }
const shared_ptr<vector<string>> get_file() const{return file;}
std::set<line_no>::iterator
begin(){ return lines->begin();}
std::set<line_no>::iterator
end(){ return lines->end();}
private:
string sought;
shared_ptr<set<line_no>> lines;
shared_ptr<vector<string>> file;
};
ostream &print(ostream & os, const QueryResult &qr) {
os << qr.sought << " occurs " << qr.lines->size() << " "
<< (((qr.lines->size()) > 1)? " times " : " time ") << endl;
for(auto num : *qr.lines) {
os << "\t(line " << num + 1 << ") "
<< *(qr.file->begin() + num) << endl;
}
return os;
}
#endif // _QUERYRESULT_H_
客户端
#include "TextQuery.h"
#include "Query_base.h"
#include "Query.h"
#include "AndQuery.h"
#include "OrQuery.h"
#include "NotQuery.h"
std::ostream& operator<<(std::ostream& os, const Query& query) {
return os << query.rep();
}
int main() {
ifstream fin;
fin.open("test.txt");
TextQuery tq(fin);
std::string s1 = "fiery", s2 = "bird", s3 = "wind";
std::string s4 = "Daddy", s5 = "Alice", s6 = "hair";
cout << "=============================\n";
// Query q0 = Query(s4);
// Query q1 = ~Query(s5);
// Query q2 = Query(s5) | Query(s6);
// Query q3 = Query(s5) & Query(s6);
Query q4 = Query(s1) & Query(s2) | Query(s3);
//q0.setDebug(0);
cout << "=============================\n";
// cout << q0 << endl;
// cout << q1 << endl;
// cout << q2 << endl;
// cout << q3 << endl;
cout << q4 << endl;
cout << "=============================\n";
// print(cout, q0.eval(tq));
// print(cout, q1.eval(tq));
// print(cout, q2.eval(tq));
// print(cout, q3.eval(tq));
print(cout, q4.eval(tq));
return 0;
}