[2018年5月27号]C++ primer 课后练习 第十五章 面向对象程序设计

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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值