textquery.h
#ifndef _TEXTQUERY_H#define _TEXTQUERY_H#include <iostream>#include <map>#include <set>#include <fstream>#include <sstream>#include <memory>#include <vector>#include <string>#include <algorithm>class QueryResult; //查詢結果類class TextQuery; //文本查詢類using line_no = std::vector<std::string>::size_type;//查詢結果類class QueryResult{ friend class TextQuery; friend std::ostream &Operator<<(std::ostream &os, const QueryResult &q);public: QueryResult() = default; QueryResult(std::string q_Word, std::shared_ptr<std::set<line_no>> lines, std::shared_ptr<std::vector<std::string>> word_file) : q_word_(q_word), lines_(lines), word_file_(word_file) {} std::set<line_no>::iterator begin(); std::set<line_no>::iterator end(); std::shared_ptr<std::vector<std::string>> get_file();PRivate: std::string q_word_; //要查詢的單詞 std::shared_ptr<std::set<line_no>> lines_; //出現行號的集合 std::shared_ptr<std::vector<std::string>> word_file_; //單詞文件};//文本查詢類class TextQuery{ friend class QueryResult;public: TextQuery() = default; TextQuery(std::ifstream &is); //查詢函數 QueryResult query(const std::string &word) const;private: std::shared_ptr<std::vector<std::string>> m_file_; //查詢的文本 std::map<std::string, std::shared_ptr<std::set<line_no>>> m_word_line_; //每個單詞以及它的行號集合};//Query_base抽象基類,制定一個標準class Query_base{ friend class Query;protected: virtual ~Query_base() = default;private: //eval返回與當前TextQuery匹配的QueryResult virtual QueryResult eval(const TextQuery &) const = 0; //rep表示查詢的一個string virtual std::string rep() const = 0;};//接口類,基類包括派生類都可以通過Query來使用,隱藏實現//Query包裝了Query_baseclass Query{ friend Query operator~(const Query &); //非 friend Query operator&(const Query &, const Query &); //與 friend Query operator|(const Query &, const Query &); //或 friend std::ostream &operator<<(std::ostream &os, const Query &query);public: Query(const std::string &query_word); QueryResult eval(const TextQuery &t) const { return query_->eval(t); } std::string rep() const { return query_->rep(); }private: //構造函數定義為private,不希望一般用戶隨便定義Query_base對象。 //注意:友元類可以訪問protected和private成員。 Query(std::shared_ptr<Query_base> query) : query_(query) {} //通過智能指針實現動態綁定 std::shared_ptr<Query_base> query_; //查詢};//派生類class WordQuery : public Query_base{ friend class Query; WordQuery(const std::string &query_word) : query_word_(query_word) {} //查詢單詞 QueryResult eval(const TextQuery &t) const { return t.query(query_word_); } //查詢的一個string std::string rep() const { return query_word_; }private: std::string query_word_; //要查找的單詞 };//無論哪種查詢都是建立在WordQuery的根本上,因此 Query的構造函數用一個WordQuery來初始化 inline Query::Query(const std::string &query_word) : query_(new WordQuery(query_word)) {}//非查詢類class NotQuery : public Query_base{ friend Query operator~(const Query &query); NotQuery(const Query &query) : query_(query) {} //覆蓋純虛函數 QueryResult eval(const TextQuery &) const override; std::string rep() const override { return "~(" + query_.rep() + ")"; }private: Query query_; //查詢對象};inline Query operator~(const Query &query){ return std::shared_ptr<Query_base>(new NotQuery(query));}//兩個運算符的抽象基類 class BinaryQuery : public Query_base{protected: BinaryQuery(const Query &left, const Query &right, std::string op) : left_(left), right_(right), op_(op) {} std::string rep() const override { return "(" + left_.rep() + " " + op_ + right_.rep() + ")"; } //因為eval函數還沒有定義,所以BinaryQuery還是抽象類 Query left_; //左操作數 Query right_; //右操作數 std::string op_; //操作符};//與操作類class AndQuery : public BinaryQuery{ friend Query operator&(const Query &left, const Query &right); AndQuery(const Query &left, const Query &right) : BinaryQuery(left, right, "&") {} QueryResult eval(const TextQuery &t) const;};inline Query operator&(const Query &left, const Query &right){ return std::shared_ptr<Query_base>(new AndQuery(left, right));}//或操作類class OrQuery : public BinaryQuery{ friend Query operator|(const Query &left, const Query &right); OrQuery(const Query &left, const Query &right) : BinaryQuery(left, right, "|") {} QueryResult eval(const TextQuery &t) const;};inline Query operator|(const Query &left, const Query &right){ return std::shared_ptr<Query_base>(new OrQuery(left, right));}#endiftextquery.cpp#include "textquery.h"//QueryResultstd::ostream &operator<<(std::ostream &os, const QueryResult &result){ os << "單詞出現了:" << result.lines_->size() << "次/n"; for (line_no i : *result.lines_) { os << " " << "line(" << i + 1 << ") "; os << (*(result.word_file_))[i] << "/n"; } return os;}std::set<line_no>::iterator QueryResult::begin(){ return lines_->begin();}std::set<line_no>::iterator QueryResult::end(){ return lines_->end();}std::shared_ptr<std::vector<std::string>> QueryResult::get_file(){ return word_file_;}//TextQuery//構造函數TextQuery::TextQuery(std::ifstream &is) : m_file_(new std::vector<std::string>){ std::string word; //單詞 std::string line; //一行文本 static int i = 0; //行號 while (std::getline(is, line)) { m_file_->push_back(line); //存入vactor<string>的末尾 i = m_file_->size() - 1; //最后一行的行號 std::istringstream ist(line); while (ist >> word) { auto &li = m_word_line_[word]; //單詞word所在的行號集 if (!li) { //為空,創建一個set<line_no> li.reset(new std::set<line_no>); } //不為空 li->insert(i); } }}//單詞查詢QueryResult TextQuery::query(const std::string &word) const{ static std::shared_ptr<std::set<line_no>> nodata(new std::set<line_no>); //指向行號集的指針 auto ret = m_word_line_.find(word); if (ret == m_word_line_.end()) { return QueryResult(word, nodata, m_file_); } else { return QueryResult(word, ret->second, m_file_); }}std::ostream &operator<<(std::ostream &os, const Query &query){ return os << query.rep();}//NotQueryQueryResult NotQuery::eval(const TextQuery &text) const { auto result = query_.eval(text); //文本查詢的結果集合 auto ret_lines = std::make_shared<std::set<line_no>>(); //行號集合 auto begin = result.begin(); auto end = result.end(); auto sz = result.get_file()->size(); //文本總行數 for (std::size_t n = 0; n != sz; ++n) { if (begin == end || *begin != n) { ret_lines->insert(n); } else if (begin != end) { ++begin; } } return QueryResult(rep(), ret_lines, result.get_file());}//AndQueryQueryResult AndQuery::eval(const TextQuery &text) const{ auto left = left_.eval(text); auto right = right_.eval(text); auto ret_lines = std::make_shared<std::set<line_no>>(); //將兩個范圍的交集寫入一個目的迭代器中 //本次調用的目的迭代器向ret_lines添加元素 set_intersection(left.begin(), left.end(), right.begin(), right.end(), inserter(*ret_lines, ret_lines->begin())); return QueryResult(rep(), ret_lines, left.get_file());}//OrQueryQueryResult OrQuery::eval(const TextQuery &text) const{ auto left = left_.eval(text); auto right = right_.eval(text); auto ret_lines = std::make_shared<std::set<line_no>>(left.begin(), left.end()); ret_lines->insert(right.begin(), right.end()); return QueryResult(rep(), ret_lines, left.get_file());}main.cpp#include "textquery.h"int main(int argc, char *argv[]){ std::ifstream is(argv[1]); TextQuery t1(is); std::string word; Query q = Query("fiery") & Query("bird") | Query("wind"); std::cout << q << std::endl; std::cout << q.eval(t1) << std::endl; std::cin.get(); return 0;}測試文本 file.txtAlice Emma has long flowing red hair.Her Daddy says when the wind blowsthrough her hair, it looks almost alive,like a fiery bird in flight.A beautiful fiery bird, he tells her,magical but untamed."Daddy, shush, there is no such thing,"she tells him, at the same time wantinghim to tell her more.Shyly, she asks, "I mean, Daddy, is there?"
新聞熱點
疑難解答
圖片精選