首页 > 代码库 > C++ 文本查询2.0(逻辑查询)

C++ 文本查询2.0(逻辑查询)

代码实例实现了继承和友元之间的关系,以及为了隐藏实际继承实现,而实现的接口类,代码偏乱,楼主- -自看的(提醒作用)

 

TextQuery.h

 1 //
 2 // Created by 徐爱东 on 17/7/19.
 3 //
 4 
 5 #ifndef TEXTQUERY_2_0_TEXTQUERY_H
 6 #define TEXTQUERY_2_0_TEXTQUERY_H
 7 
 8 #include <iostream>
 9 #include <map>
10 #include <set>
11 #include <vector>
12 #include <string>
13 #include <memory>
14 #include <sstream>
15 #include <fstream>
16 
17 
18 class QueryResult
19 {
20     friend std::ostream &operator<<(std::ostream &os, const QueryResult &result);
21 
22     typedef std::vector<std::string>::size_type line_no;
23 public:
24     QueryResult(const std::string &word, std::shared_ptr<std::set<line_no> > lines,
25                 std::shared_ptr<std::vector<std::string>> files);
26 
27     std::set<line_no>::iterator begin()
28     {
29         return lines_->begin();
30     }
31 
32     std::set<line_no>::iterator end()
33     {
34         return lines_->end();
35     }
36 
37     std::shared_ptr<std::vector<std::string> > get_file()
38     {
39         return files_;
40     }
41 
42 private:
43     std::string word_;    //查询单词
44     std::shared_ptr<std::set<line_no>> lines_;    //单词出现行数集合
45     std::shared_ptr<std::vector<std::string>> files_;          //根据的文件
46 
47 };
48 
49 
50 class TextQuery
51 {
52 public:
53     // using line_no=std::vector<std::string>::size_type ;
54     typedef std::vector<std::string>::size_type line_no;    //C++11
55 
56 
57     TextQuery(std::fstream &in);
58 
59     QueryResult query(const std::string &word) const;
60 
61 private:
62     std::shared_ptr<std::vector<std::string> > filecontext_;      //文件内容
63     std::map<std::string, std::shared_ptr<std::set<line_no> > > wordlinesset_;      //单词集合
64 };
65 
66 
67 #endif //TEXTQUERY_2_0_TEXTQUERY_H

 

TextQuery.cpp

 1 //
 2 // Created by 徐爱东 on 17/7/19.
 3 //
 4 
 5 #include "TextQuery.h"
 6 
 7 QueryResult::QueryResult(const std::string &word, std::shared_ptr<std::set<line_no> > lines,
 8                          std::shared_ptr<std::vector<std::string>> files)
 9         : word_(word), lines_(lines), files_(files)
10 {
11 
12 }
13 
14 
15 std::ostream &operator<<(std::ostream &os, const QueryResult &result)
16 {
17     if (!result.lines_)
18     {
19         return os << result.word_ << " apprear 0 time:\n";
20 
21     } else
22     {
23         os <<"\n"<< result.word_ << " appear " << result.lines_->size()
24            << (result.lines_->size() > 1 ? " times:" : " time:") << "\n\n";
25 
26 
27         for (auto iter = result.lines_->cbegin();
28              iter != result.lines_->cend(); iter = (result.lines_->upper_bound(*iter)))
29         {
30             os << "\t\t\t\t\t(line" << *iter + 1 << "): " << *(result.files_->begin() + *iter) << std::endl<<std::endl;
31         }
32 
33         return os;
34     }
35 }
36 
37 
38 TextQuery::TextQuery(std::fstream &in)
39         : filecontext_(new std::vector<std::string>{})
40 {
41     std::string line;
42     std::stringstream stream;
43 
44     //每次获得一行
45     while (std::getline(in, line))
46     {
47         stream.clear();
48         filecontext_->push_back(line);
49         auto linenumber = filecontext_->size() - 1;
50 
51 
52         stream << line;
53         while (stream >> line)
54         {
55             //没有则创建,有则返回只能指针;
56             auto& lineset = wordlinesset_[line];
57 
58             if (!lineset)
59                 lineset.reset(new std::set<line_no>);
60 
61             //记录行号
62             lineset->insert(linenumber);
63         }
64 
65     }
66 
67 
68 }
69 
70 QueryResult TextQuery::query(const std::string &word) const
71 {
72     if (wordlinesset_.find(word) == wordlinesset_.end())
73     {
74         std::shared_ptr<std::set<line_no> > null_sharedptr(new std::set<line_no>);
75         return QueryResult(word, null_sharedptr, filecontext_);
76 
77     } else
78     {
79         return QueryResult(word, wordlinesset_.find(word)->second, filecontext_);
80     }
81 
82 }

 

Query.h & QueryBase{WordQuery,NotQuery,BinaryQuery{AndQuery,OrQUery}};

基本关系:Query是接口类,QueryBase是抽象类,WordQUery,NotQuery实现类,BinaryQuery抽象类(重构),AndQuery,OrQUery实际类

  1 //
  2 // Created by 徐爱东 on 17/7/19.
  3 //
  4 
  5 #ifndef TEXTQUERY_2_0_QUERY_BASE_H
  6 #define TEXTQUERY_2_0_QUERY_BASE_H
  7 
  8 #include "TextQuery.h"
  9 
 10 class Query;
 11 
 12 class WordQuery;
 13 
 14 class NotQuery;
 15 
 16 class AndQuery;
 17 
 18 class OrQuery;
 19 
 20 //抽象类
 21 class Query_base
 22 {
 23     //接口类,用于隐藏继承结构
 24     friend class Query;;
 25 private:
 26     virtual QueryResult eval(const TextQuery &) const =0;
 27 
 28     virtual std::string rep() const =0;
 29 
 30 protected:
 31     using line_no=TextQuery::line_no;
 32 
 33     virtual ~Query_base() = default;
 34 
 35 };
 36 
 37 
 38 class Query
 39 {
 40     friend class Query_base;
 41 
 42     friend class WordQuery;
 43 
 44     friend class NotQuery;
 45 
 46     friend class AndQuery;
 47 
 48     friend class OrQuery;
 49 
 50 
 51     //运算符操作需要访问私有shared_ptr,所以声明为友元
 52     friend Query operator~(const Query &);
 53 
 54     friend Query operator&(const Query &lhs, const Query &rhs);
 55 
 56     friend Query operator|(const Query &l, const Query &r);
 57 
 58 
 59     friend std::ostream &operator<<(std::ostream &os, const Query query)
 60     {
 61         return os << query.rep();
 62     }
 63 
 64 
 65 public:
 66     Query(const std::string &word);    //普通单单词查询,WordQuery;
 67 
 68     //接口函数,因为不是继承Query_base
 69     QueryResult eval(const TextQuery &text) const
 70     {
 71         return q->eval(text);
 72     }
 73 
 74     std::string rep() const
 75     {
 76         return q->rep();
 77     }
 78 
 79 private:
 80     //shared_ptr构造,为了使用动态虚调用
 81     //private 不允许外部调用
 82     Query(std::shared_ptr<Query_base> query) : q(query)
 83     {};
 84     std::shared_ptr<Query_base> q;
 85 };
 86 
 87 
 88 //唯一实际查询的类
 89 class WordQuery : public Query_base
 90 {
 91     //所有成员皆为private
 92     friend class Query;     //Query 需要使用构造函数
 93 
 94     std::string word_;
 95 
 96     WordQuery(const std::string &word) : word_(word)
 97     {}
 98 
 99 
100     QueryResult eval(const TextQuery &Tq) const override
101     {
102         return Tq.query(word_);
103     }
104 
105     std::string rep() const override
106     {
107         return word_;
108     }
109 
110 };
111 
112 
113 //取反的Query
114 class NotQuery : public Query_base
115 {
116 
117     friend Query operator~(const Query &);
118 
119     NotQuery(const Query &q) : query_(q)
120     {
121 
122     }
123 
124     Query query_;
125 
126     //"~单词"返回的结果
127     QueryResult eval(const TextQuery &Tq) const override
128     {
129         auto result = query_.eval(Tq);
130 
131         auto ret_line = std::make_shared<std::set<std::vector<std::string>::size_type>>();
132         auto set = std::make_shared<std::set<std::vector<std::string>::size_type> >(result.begin(), result.end());
133 
134         auto file_line = result.get_file()->size();
135 
136         for (auto line = 0; line != file_line; line++)
137         {
138             //不在set里
139             if (set->find(line + 1) == set->end())
140             {
141                 //添加
142                 ret_line->insert(line);
143             }
144         }
145 
146         return QueryResult(query_.rep(), ret_line, result.get_file());
147 
148     }
149 
150     std::string rep() const override
151     {
152         return "~(" + query_.rep() + ")";//表示不需要查询的单词
153     }
154 };
155 
156 
157 
158 
159 //BinaryQuery类,一个抽象基类,因为继承了基类的纯虚函数eval()
160 //重构
161 class BinaryQuery : public Query_base
162 {
163     friend class Query;;
164 protected:
165     BinaryQuery(const Query &l, const Query &r, const std::string &operaname)
166             : lhs_(l),
167               rhs_(r),
168               operaname_(operaname)
169     {
170 
171     }
172 
173     Query lhs_, rhs_;
174     std::string operaname_;
175 
176 //    QueryResult eval(const TextQuery &) const
177 //    {
178 //
179 //    }
180 
181     std::string rep() const
182     {
183         return "(" + lhs_.rep() + " " + operaname_ + " " + rhs_.rep() + ")";
184     }
185 };
186 
187 class AndQuery : public BinaryQuery
188 {
189     friend class Query;;
190 protected:
191     friend Query operator&(const Query &, const Query &);
192 
193     AndQuery(const Query &l, const Query &r) : BinaryQuery(l, r, "&")
194     {}
195 
196     QueryResult eval(const TextQuery &text) const
197     {
198         //通过Query成员进行虚调用
199         //调用eval返回每个QueryResult结果
200         auto right = lhs_.eval(text), left = rhs_.eval(text);
201         //空的目标容器
202         auto ret_lines = std::make_shared<std::set<std::vector<std::string>::size_type>>();
203 
204         //取交集放入re_lines;
205         std::set_intersection(right.begin(), right.end(),
206                               left.begin(), left.end(),
207                               std::inserter(*ret_lines, ret_lines->begin()));
208 
209         return QueryResult(rep(), ret_lines, right.get_file());
210     }
211 
212 };
213 
214 
215 
216 class OrQuery : public BinaryQuery
217 {
218     friend class Query;;
219 protected:
220     friend Query operator|(const Query &, const Query &);
221 
222     OrQuery(const Query &l, const Query &r) : BinaryQuery(l, r, "|")
223     {}
224 
225     QueryResult eval(const TextQuery &text) const
226     {
227         //通过Query成员lhs和rhs进行虚调用
228         //调用eval返回每个运算对象的QueryResult
229         auto right = lhs_.eval(text), left = rhs_.eval(text);
230         auto ret_lines = std::make_shared<std::set<std::vector<std::string>::size_type> >(right.begin(), right.end());
231         //进行并集操作y
232         ret_lines->insert(left.begin(), left.end());
233         return QueryResult(rep(), ret_lines, right.get_file());
234     }
235 };
236 
237 //每个Query都先生成基本WordQuery基础
238 inline Query::Query(const std::string &word) : q(new WordQuery(word))
239 { std::cout << "Query" << std::endl; }
240 
241 
242 
243 inline Query operator~(const Query &q)
244 {
245     return std::shared_ptr<Query_base>(new NotQuery(q));
246 }
247 
248 inline Query operator&(const Query &lhs, const Query &rhs)
249 {
250     return std::shared_ptr<Query_base>(new AndQuery(lhs, rhs));
251 }
252 
253 inline Query operator|(const Query &l, const Query &r)
254 {
255     return std::shared_ptr<Query_base>(new OrQuery(l, r));
256 }
257 
258 
259 #endif //TEXTQUERY_2_0_QUERY_BASE_H

 

 

main.cpp

 1 #include <iostream>
 2 #include "Query_base.h"
 3 
 4 
 5 int main()
 6 {
 7     std::fstream file_("Text.txt", std::ios::in);
 8     std::vector<std::string> str_vec;
 9     std::vector<Query> que_vec;
10 
11     if (file_.is_open())
12     {
13         TextQuery file(file_);
14 
15         std::string word1, word2;
16         do
17         {
18             std::cout << "Input word you want(‘quit to exit‘): ";
19             std::cin >> word1 >> word2;
20 
21             if (word1 == "quit")
22             {
23                 break;
24             }
25 
26 
27             Query query1(word1), query2(word2);
28             auto q = query1 & query2;
29             std::cout << q.rep() << std::endl;
30             std::cout << q.eval(file) << std::endl;
31             word1.clear();
32         } while (1);
33 
34     }
35 
36     file_.close();
37 
38     return 0;
39 }

缺点:本来想实现字符串读取分隔实现动态逻辑Query联合,太麻烦- -就没写

C++ 文本查询2.0(逻辑查询)