Primer C++(第十五章)--文本查询

文本查询

支持功能

  • 单词查询
  • 逻辑非查询
  • 逻辑或查询
  • 逻辑与查询
  • 以及混合查询

    查询子系统类图

    在这里插入图片描述

    门面类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;
}

点击下载

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦