面向对象编程
--再谈文本查询示例[续/习题]
//P522 习题15.41 //1 in TextQuery.h #ifndef TEXTQUERY_H_INCLUDED #define TEXTQUERY_H_INCLUDED #include <iostream> #include <fstream> #include <sstream> #include <vector> #include <set> #include <map> #include <string> #include <stdexcept> using namespace std; class TextQuery { public: typedef std::vector<std::string>::size_type line_no; typedef string::size_type str_size; void read_file(std::ifstream &is) { store_file(is); build_map(); } std::set<line_no> run_query(const std::string &) const; std::string text_line(line_no) const; line_no size() const; private: void store_file(std::ifstream &); void build_map(); std::vector<std::string> line_of_text; std::map< std::string,std::set<line_no> > word_map; }; #endif // TEXTQUERY_H_INCLUDED
//2 in TextQuery.cpp #include "TextQuery.h" void TextQuery::store_file(ifstream &is) { string textline; while (getline(is,textline)) { line_of_text.push_back(textline); } } void TextQuery::build_map() { for (line_no line_num = 0; line_num != line_of_text.size(); ++line_num) { istringstream line(line_of_text[line_num]); string word; while (line >> word) { word_map[word].insert(line_num); } } } set<TextQuery::line_no> TextQuery::run_query(const std::string &query_word) const { map<string,set<line_no> >::const_iterator loc = word_map.find(query_word); if (loc == word_map.end()) { return set<TextQuery::line_no>(); } else { return loc -> second; } } string TextQuery::text_line(line_no line) const { if (line < line_of_text.size()) { return line_of_text[line]; } throw out_of_range("line number out of range"); } TextQuery::str_size TextQuery::size() const { return line_of_text.size(); }
//3 in Query.h #ifndef QUERY_H_INCLUDED #define QUERY_H_INCLUDED #include "TextQuery.h" #include <iostream> #include <fstream> #include <string> #include <set> #include <algorithm> using namespace std; class Query_base { friend class Query; protected: typedef TextQuery::line_no line_no; virtual ~Query_base() {} private: virtual set<line_no> eval(const TextQuery &) const = 0; virtual ostream &display(ostream & = cout) const = 0; }; 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 &); Query(const Query &c):p(c.p),use(c.use) { ++ *use; } ~Query() { decr_use(); } Query &operator=(const Query &); set<TextQuery::line_no> eval(const TextQuery &t) const { return p -> eval(t); } ostream &display(ostream &os) const { return p -> display(os); } private: Query(Query_base *query): p(query),use(new std::size_t(1)) {} Query_base *p; std::size_t *use; void decr_use() { if ( -- *use == 0 ) { delete p; delete use; } } }; inline Query & Query::operator=(const Query &rhs) { ++ * rhs.use; decr_use(); p = rhs.p; use = rhs.use; return *this; } inline ostream & operator<<(ostream &os,const Query &q) { return q.display(os); } class WordQuery : public Query_base { friend class Query; WordQuery(const string &s):query_word(s) {} set<line_no> eval(const TextQuery &t) const { return t.run_query(query_word); } ostream &display(ostream &os) const { return os << query_word; } string query_word; }; inline Query::Query(const string &s): p(new WordQuery(s)),use(new std::size_t(1)) {} class NotQuery : public Query_base { friend Query operator~(const Query &); NotQuery(Query q):query(q) {} set<line_no> eval(const TextQuery &) const; ostream &display(ostream &os) const { return os << "~(" << query << ")"; } const Query query; }; class BinaryQuery : public Query_base { protected: BinaryQuery(Query left,Query right,string op): lhs(left),rhs(right),oper(op) {} ostream &display(ostream &os) const { return os << "(" << lhs << " " << oper << " " << rhs << ")"; } const Query lhs,rhs; const string oper; }; class AndQuery : public BinaryQuery { friend Query operator&(const Query &,const Query &); AndQuery(Query left,Query right): BinaryQuery(left,right,"&"){} set<line_no> eval(const TextQuery &) const; }; class OrQuery : public BinaryQuery { friend Query operator|(const Query &,const Query &); OrQuery(Query left,Query right): BinaryQuery(left,right,"|"){} set<line_no> eval(const TextQuery &) const; }; inline Query operator&(const Query &lhs,const Query &rhs) { return new AndQuery(lhs,rhs); } inline Query operator|(const Query &lhs,const Query &rhs) { return new OrQuery(lhs,rhs); } inline Query operator~(const Query &oper) { return new NotQuery(oper); } #endif // QUERY_H_INCLUDED
//4 in Query.cpp #include "Query.h" set<TextQuery::line_no> OrQuery::eval(const TextQuery &file) const { set<line_no> left = lhs.eval(file), ret_lines = rhs.eval(file); ret_lines.insert(left.begin(),left.end()); return ret_lines; } set<TextQuery::line_no> AndQuery::eval(const TextQuery &file) const { set<line_no> left = lhs.eval(file), right = rhs.eval(file); set<line_no> ret_lines; set_intersection(left.begin(),left.end(), right.begin(),right.end(), inserter(ret_lines,ret_lines.begin())); return ret_lines; } set<TextQuery::line_no> NotQuery::eval(const TextQuery &file) const { set<line_no> hav_val = query.eval(file); set<line_no> ret_val; for (line_no n = 0; n != file.size(); ++n) { if (hav_val.find(n) == hav_val.end()) { ret_val.insert(n); } } return ret_val; }
//5 in main.cpp //测试数据与前面相同 #include <iostream> #include <algorithm> #include "TextQuery.h" #include "Query.h" using namespace std; int main() { ifstream inFile("input"); TextQuery file; file.read_file(inFile); Query q = Query("fiery") & Query("bird") | Query("wind"); cout << "Executed Query for :" << q << endl; typedef set<TextQuery::line_no> line_nums; const line_nums &locs = q.eval(file); cout << "match occurs " << locs.size() << " times" << endl; line_nums::const_iterator it = locs.begin(); for (; it != locs.end(); ++it) { cout << "\t(line " << (*it) + 1 << ") " << file.text_line(*it) << endl; } }
运行示例:
时间: 2024-11-04 08:43:35