// 文本查询程序-类.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<string>
#include<iostream>
#include<memory>
#include<sstream>
#include<set>
#include<map>
#include<vector>
#include<algorithm>
#include<iterator>
#include<fstream>
using namespace std;
class QueryResult//储存查询结果并输出!
{
public:
using line_no = vector<string>::size_type;
QueryResult(string s, shared_ptr<set<line_no>> p, shared_ptr<vector<string>> f) :find_word(s), lines(p), file(f) {}
friend ostream &print(ostream &os, const QueryResult &qr);
set<line_no>::const_iterator begin()const { return lines->cbegin(); }
set<line_no>::const_iterator end()const { return lines->cend(); }
const shared_ptr<vector<string>> get_file()const { return file; }
private:
string find_word;
shared_ptr<set<line_no>> lines;
shared_ptr<vector<string>> file;
};
ostream &print(ostream &os, const QueryResult &qr)
{
os << qr.find_word << " occurs " << qr.lines->size() << " times" << endl;
for (auto &num : *(qr.lines))
{
os << "\t(line " << num + 1 << ") " << *(qr.file->begin() + num) << endl;
}
return os;
}
class TextQuery//读取文件,并返回查询结果至存储类!
{
public:
using line_no = vector<string>::size_type;
TextQuery() = default;
TextQuery(istream &in) { read(in); }
void read_from_file(istream &in) { read(in); }
QueryResult query(const string &find_word) const; //创建queryresult对象!
private:
void read(istream &in);
shared_ptr<vector<string>> file = make_shared<vector<string>>(); // 如果创建空的只能指针,必须进行绑定(初始化)才可以使用!为什么不能使用new?
map<string, shared_ptr<set<line_no>>> wm; //共享数据,避免拷贝增加计算量!
};
QueryResult TextQuery::query(const string &find_word) const
{
if (wm.find(find_word) == wm.cend())
{
return QueryResult(find_word, nullptr, file);
}
else
{
return QueryResult(find_word, wm.at(find_word), file);
}
}
void TextQuery::read(istream &in)
{
string text;
while (getline(in, text))
{
file->push_back(text);
int n = file->size() - 1;
istringstream line(text);
string word;
while (line >> word)
{
auto &lines = wm[word];
if (!lines) //如果为空指针,则重新指向new set<line_no>
lines.reset(new set<line_no>);
lines->insert(n);
}
}
}
class Query_base
{
friend class Query;
protected:
using line_no = TextQuery::line_no;
virtual ~Query_base() = default;
private:
virtual QueryResult eval(const TextQuery&) const = 0;
virtual string rep() const = 0;
};
class WordQuery :public Query_base
{
friend class Query;
WordQuery(const string &s) :query_word(s) {}//Query的构造函数要调用此构造函数,因此必须前置!
QueryResult eval(const TextQuery &t)const { return t.query(query_word); }
string rep()const { return query_word; }
string query_word;
};
class Query
{
friend Query operator~(const Query &);
friend Query operator|(const Query &, const Query&);
friend Query operator&(const Query &, const Query&);
public:
Query(const string &s) :q(new WordQuery(s)) {} //创建wordQuery指针对象,用Query_Base指针指向!
QueryResult eval(const TextQuery &t)const { return q->eval(t); }
string rep()const { return q->rep(); }
friend ostream &operator<<(ostream &os, const Query &query);
private:
Query(shared_ptr<Query_base> query):q(query){}
shared_ptr<Query_base> q;
};
ostream &operator<<(ostream &os, const Query &query)
{
return os << query.rep();
}
class NotQuery :public Query_base
{
friend Query operator~(const Query&);
NotQuery(const Query &q):query(q){}
string rep()const { return "~(" + query.rep() + ")"; }
QueryResult eval(const TextQuery&)const;
Query query;
};
inline Query operator~(const Query &operand)
{
return shared_ptr<Query_base>(new NotQuery(operand));
}
class BinaryQuery:public Query_base
{
protected:
BinaryQuery(const Query &l,const Query &r,string s):lhs(l),rhs(r),opSym(s){}
string rep()const { return "(" + lhs.rep() + " " + opSym + " " + rhs.rep() + ")"; }
Query lhs, rhs;
string opSym;
};
class AndQuery:public BinaryQuery
{
friend Query operator&(const Query&, const Query&);
AndQuery(const Query &left, const Query &right) :BinaryQuery(left, right, "&") {};
QueryResult eval(const TextQuery &)const;
};
inline Query operator&(const Query &lhs, const Query &rhs)
{
return shared_ptr<Query_base>(new AndQuery(lhs, rhs));
}
class OrQuery:public BinaryQuery
{
friend Query operator|(const Query&, const Query&);
OrQuery(const Query &left, const Query &right) :BinaryQuery(left, right,"|") {}
QueryResult eval(const TextQuery &)const;
};
inline Query operator|(const Query &lh, const Query &rh)
{
return shared_ptr<Query_base>(new OrQuery(lh, rh));
}
QueryResult OrQuery::eval(const TextQuery &text)const
{
using line_no = vector<string>::size_type;
auto right = rhs.eval(text), left = lhs.eval(text);
auto ret_lines = make_shared<set<line_no>>(left.begin(), left.end());
ret_lines->insert(right.begin(),right.end()); //set.inser(b,e)
return QueryResult(rep(), ret_lines, left.get_file());
}
QueryResult AndQuery::eval(const TextQuery &text)const
{
using line_no = vector<string>::size_type;
auto left = lhs.eval(text), right = rhs.eval(text);
auto ret_lines = make_shared<set<line_no>>();
set_intersection(left.begin(), left.end(), right.begin(), right.end(), inserter(*ret_lines, ret_lines->begin()));//插入迭代器inserter
return QueryResult(rep(),ret_lines,left.get_file());
}
QueryResult NotQuery::eval(const TextQuery &text)const
{
using line_no = vector<string>::size_type;
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());
}
int main()
{
string filename = "C:\\Users\\winack\\Documents\\Visual Studio 2017\\Projects\\文本查询程序-My-继承、\\123.txt";
ifstream file(filename);
TextQuery info(file);
Query q = Query("is") & Query("the") | Query("have");
//cout << q;
print(cout, q.eval(info));
q = Query("and");//Query自动合成拷贝构造函数!
print(cout, q.eval(info));
return 0;
}
文本查询程序-类
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 这篇文章是本人在学习C++primer第15章Query程序时对自己所遇到困惑的总结,我发现其实这节最难理解的...