15.39
QueryResult AndQuery::eval(const TextQuery& t)const {
auto lQueryResult = lhs.eval(t);
auto rQueryResult = rhs.eval(t);
auto finalResult = make_shared<set<line_no>>();
set_intersection(lQueryResult.begin(), lQueryResult.end(), rQueryResult.begin(), rQueryResult.end(), inserter(*finalResult, finalResult->begin()));
return QueryResult(rep(), finalResult, lQueryResult.get_file());
}
QueryResult OrQuery::eval(const TextQuery& t)const {
auto lQueryResult = lhs.eval(t);
auto rQueryResult = rhs.eval(t);
auto finalResult = make_shared<set<line_no>>(lQueryResult.begin(), lQueryResult.end());
finalResult->insert(rQueryResult.begin(), rQueryResult.end());
return QueryResult(rep(), finalResult, lQueryResult.get_file());
}
class NotQuery : public Query_base {
friend Query operator~(const Query& q);
NotQuery(const Query& q):query(q){ cout << "NotQuery()" << endl; }
QueryResult eval(const TextQuery & t)const;
string rep()const { cout << "NotQuery::rep()" << endl; return "~(" + query.rep() +")" ;}
Query query;
};
15.40
猜测,正常执行,当全为空集,不会有查询结果
15.41
class Query_base {
friend class Query;
protected:
virtual ~Query_base() = default;
private:
virtual QueryResult eval(const TextQuery&) const = 0;
virtual string rep() const = 0;
};
class Query {
friend Query operator~(const Query&);
friend Query operator|(const Query& lq, const Query& rq);
friend Query operator&(const Query& lq, const Query& rq);
public:
Query(const string&);
Query(const Query& q):q(q.q),use_count(q.use_count){++*use_count;}
Query(Query& q) :q(q.q), use_count(q.use_count) { ++*use_count; }
Query& operator= (const Query & q);
QueryResult eval(const TextQuery & t)const { return q->eval(t); }
string rep()const { return q->rep(); }
~Query(){
if(--*use_count == 0){
delete q;
delete use_count;
}
}
private:
Query(Query_base* theQ) : q(theQ), use_count(new size_t(1)) { cout << "Query(shared_ptr<Query_base> theQ" << endl; }
Query_base* q;
size_t* use_count;
};
Query& Query::operator= (const Query & q) {
if (this != &q) {
if (--*this->use_count == 0) {
delete this->q;
delete use_count;
}
this->q = q.q;
this->use_count = q.use_count;
++*this->use_count;
}
return *this;
}
ostream& operator<<(ostream& os, const Query& q) {
os << q.rep();
return os;
}
class WordQuery : public Query_base {
friend class Query;
WordQuery(const string & s) :query_word(s) { cout << "WordQuery(const string & s)" << endl; }
QueryResult eval(const TextQuery & t)const { return t.query(query_word); }
string rep()const {
//cout << "WordQuery::rep()" << endl;
return query_word;
}
string query_word;
};
inline Query::Query(const string& s) : q(new WordQuery(s)),use_count(new size_t(1)) { cout << "Query(const string &)" << endl; }
class NotQuery : public Query_base {
friend Query operator~(const Query& q);
NotQuery(const Query& q) :query(q) { cout << "NotQuery()" << endl; }
QueryResult eval(const TextQuery & t)const;
string rep()const {
//cout << "NotQuery::rep()" << endl;
return "~(" + query.rep() + ")";
}
Query query;
};
QueryResult NotQuery::eval(const TextQuery& t)const {
auto queryResult = query.eval(t);
auto finalResult = make_shared<set<line_no>>();
size_t sz = queryResult.get_file()->size();
auto beg = queryResult.begin(), end = queryResult.end();
for (size_t i = 0; i != sz; i++) {
if (beg == end || *beg != i) {
finalResult->insert(i);
}
else if (beg != end) {
beg++;
}
}
return QueryResult(rep(), finalResult, queryResult.get_file());
}
Query operator~(const Query& q) {
return new NotQuery(q);
}
class BinaryQuery :public Query_base {
protected:
BinaryQuery(const Query& l, const Query& r, const string& s) :lhs(l), rhs(r), opSym(s) { cout << "BinaryQuery(const Query& l , const Query& r, const string& s)" << endl; }
string rep()const {
//cout<< "BinaryQuery::rep()" << endl;
return "(" + lhs.rep() + " " + opSym + " " + rhs.rep() + ")";
}
protected:
Query lhs, rhs;
string opSym;
};
class AndQuery : public BinaryQuery {
friend Query operator&(const Query& lq, const Query& rq);
AndQuery(const Query & lq, const Query & rq) : BinaryQuery(lq, rq, "&") { cout << "AndQuery(const Query & lq, const Query & rq)" << endl; }
QueryResult eval(const TextQuery& t)const;
};
Query operator&(const Query& lq, const Query& rq) {
cout << "operator&(const Query& lq, const Query& rq)" << endl;
return new AndQuery(lq, rq);
}
QueryResult AndQuery::eval(const TextQuery& t)const {
auto lQueryResult = lhs.eval(t);
auto rQueryResult = rhs.eval(t);
auto finalResult = make_shared<set<line_no>>();
set_intersection(lQueryResult.begin(), lQueryResult.end(), rQueryResult.begin(), rQueryResult.end(), inserter(*finalResult, finalResult->begin()));
return QueryResult(rep(), finalResult, lQueryResult.get_file());
}
class OrQuery : public BinaryQuery {
friend Query operator|(const Query& lq, const Query& rq);
OrQuery(const Query & lq, const Query & rq) : BinaryQuery(lq, rq, "|") { cout << "OrQuery(const Query & lq, const Query & rq)" << endl; }
QueryResult eval(const TextQuery& t)const;
};
Query operator|(const Query& lq, const Query& rq) {
cout << "operator|(const Query& lq, const Query& rq)" << endl;
return new OrQuery(lq, rq);
}
QueryResult OrQuery::eval(const TextQuery& t)const {
auto lQueryResult = lhs.eval(t);
auto rQueryResult = rhs.eval(t);
shared_ptr<set<line_no>>& finalResult = make_shared<set<line_no>>(lQueryResult.begin(), lQueryResult.end());
finalResult->insert(rQueryResult.begin(), rQueryResult.end());
return QueryResult(rep(), finalResult, lQueryResult.get_file());
}
修改后的代码如上,主要不使用只能指针后,需要我们自己来计算当前动态内存所使用的对象,在析构时进行判断并适时进行释放操作
15.42
c:
给TextQuery增加一个带set的构造函数,在执行时输入需要查询的行
TextQuery(ifstream& ifs, const set<int > setInt) :file(new StrVec()) {
string lineStr, word;
while (getline(ifs, lineStr))
{
file->push_back(lineStr);
int lineCount = file->size();
if(setInt.find(lineCount) == setInt.end()){
continue;
}
istringstream ist(lineStr);
while (ist >> word)
{
shared_ptr<set<line_no>>& line = wm[word];
if (!line) {
line.reset(new set<line_no>);
}
line->insert(lineCount);
}
}
};
int main() {
{
ifstream ifs("queryWord.txt");
set<int> intSet;
int cinInt;
while(cin >> cinInt){
intSet.insert(cinInt);
}
TextQuery tq(ifs, intSet);
Query q = Query("her") | Query("she");
cout << "##############################" << endl;
print(cout, q.eval(tq));
}
for (;;);
return 0;
}