面向对象编程 --再谈文本查询示例[续/习题] view sourceprint? 01. //P522 习题15.41 02. //1 in TextQuery.h 03. #ifndef TEXTQUERY_H_INCLUDED 04. #define TEXTQUERY_H_INCLUDED 05. 06. #include <iostream> 07. #include <fstream> 08. #include <sstream> 09. #include <vector> 10. #include <set> 11. #include <map> 12. #include <string> 13. #include <stdexcept> 14. 15. using namespace std; 16. 17. class TextQuery 18. { 19. public: 20. typedef std::vector<std::string>::size_type line_no; 21. typedef string::size_type str_size; 22. 23. void read_file(std::ifstream &is) 24. { 25. store_file(is); 26. build_map(); 27. } 28. 29. std::set<line_no> run_query(const std::string &) const; 30. std::string text_line(line_no) const; 31. 32. line_no size() const; 33. 34. private: 35. void store_file(std::ifstream &); 36. void build_map(); 37. 38. std::vector<std::string> line_of_text; 39. std::map< std::string,std::set<line_no> > <a href="http://www.it165.net/edu/ebg/" target="_blank" class="keylink">word</a>_map; 40. }; 41. 42. #endif // TEXTQUERY_H_INCLUDED view sourceprint? 01. //2 in TextQuery.cpp 02. #include "TextQuery.h" 03. 04. void TextQuery::store_file(ifstream &is) 05. { 06. string textline; 07. while (getline(is,textline)) 08. { 09. line_of_text.push_back(textline); 10. } 11. } 12. 13. void TextQuery::build_map() 14. { 15. for (line_no line_num = 0; 16. line_num != line_of_text.size(); 17. ++line_num) 18. { 19. istringstream line(line_of_text[line_num]); 20. string <a href="http://www.it165.net/edu/ebg/" target="_blank" class="keylink">word</a>; 21. 22. while (line >> word) 23. { 24. word_map[word].insert(line_num); 25. } 26. } 27. } 28. 29. set<TextQuery::line_no> 30. TextQuery::run_query(const std::string &query_word) const 31. { 32. map<string,set<line_no> >::const_iterator loc = 33. word_map.find(query_word); 34. 35. if (loc == word_map.end()) 36. { 37. return set<TextQuery::line_no>(); 38. } 39. else 40. { 41. return loc -> second; 42. } 43. } 44. 45. string TextQuery::text_line(line_no line) const 46. { 47. if (line < line_of_text.size()) 48. { 49. return line_of_text[line]; 50. } 51. throw out_of_range("line number out of range"); 52. } 53. 54. TextQuery::str_size TextQuery::size() const 55. { 56. return line_of_text.size(); 57. } view sourceprint? 001. //3 in Query.h 002. #ifndef QUERY_H_INCLUDED 003. #define QUERY_H_INCLUDED 004. 005. #include "TextQuery.h" 006. #include <iostream> 007. #include <fstream> 008. #include <string> 009. #include <set> 010. #include <algorithm> 011. 012. using namespace std; 013. 014. class Query_base 015. { 016. friend class Query; 017. 018. protected: 019. typedef TextQuery::line_no line_no; 020. virtual ~Query_base() {} 021. 022. private: 023. virtual set<line_no> eval(const TextQuery &) const = 0; 024. virtual ostream &display(ostream & = cout) const = 0; 025. }; 026. 027. class Query 028. { 029. friend Query operator~(const Query &); 030. friend Query operator|(const Query &,const Query &); 031. friend Query operator&(const Query &,const Query &); 032. 033. public: 034. Query(const string &); 035. 036. Query(const Query &c):p(c.p),use(c.use) 037. { 038. ++ *use; 039. } 040. ~Query() 041. { 042. decr_use(); 043. } 044. Query &operator=(const Query &); 045. 046. set<TextQuery::line_no> 047. eval(const TextQuery &t) const 048. { 049. return p -> eval(t); 050. } 051. 052. ostream &display(ostream &os) const 053. { 054. return p -> display(os); 055. } 056. 057. private: 058. Query(Query_base *query): 059. p(query),use(new std::size_t(1)) {} 060. 061. Query_base *p; 062. std::size_t *use; 063. 064. void decr_use() 065. { 066. if ( -- *use == 0 ) 067. { 068. delete p; 069. delete use; 070. } 071. } 072. }; 073. 074. inline Query & 075. Query::operator=(const Query &rhs) 076. { 077. ++ * rhs.use; 078. decr_use(); 079. 080. p = rhs.p; 081. use = rhs.use; 082. 083. return *this; 084. } 085. 086. inline ostream & 087. operator<<(ostream &os,const Query &q) 088. { 089. return q.display(os); 090. } 091. 092. class WordQuery : public Query_base 093. { 094. friend class Query; 095. 096. WordQuery(const string &s):query_word(s) {} 097. 098. set<line_no> eval(const TextQuery &t) const 099. { 100. return t.run_query(query_word); 101. } 102. ostream &display(ostream &os) const 103. { 104. return os << query_word; 105. } 106. 107. 108. string query_word; 109. }; 110. 111. inline Query::Query(const string &s): 112. p(new WordQuery(s)),use(new std::size_t(1)) {} 113. 114. class NotQuery : public Query_base 115. { 116. friend Query operator~(const Query &); 117. NotQuery(Query q):query(q) {} 118. 119. set<line_no> eval(const TextQuery &) const; 120. 121. ostream &display(ostream &os) const 122. { 123. return os << "~(" << query << ")"; 124. } 125. 126. const Query query; 127. }; 128. 129. class BinaryQuery : public Query_base 130. { 131. protected: 132. BinaryQuery(Query left,Query right,string op): 133. lhs(left),rhs(right),oper(op) {} 134. 135. ostream &display(ostream &os) const 136. { 137. return os << "(" << lhs << " " << oper << " " 138. << rhs << ")"; 139. } 140. 141. const Query lhs,rhs; 142. const string oper; 143. }; 144. 145. class AndQuery : public BinaryQuery 146. { 147. friend Query operator&(const Query &,const Query &); 148. 149. AndQuery(Query left,Query right): 150. BinaryQuery(left,right,"&"){} 151. 152. set<line_no> eval(const TextQuery &) const; 153. }; 154. 155. class OrQuery : public BinaryQuery 156. { 157. friend Query operator|(const Query &,const Query &); 158. 159. OrQuery(Query left,Query right): 160. BinaryQuery(left,right,"|"){} 161. 162. set<line_no> eval(const TextQuery &) const; 163. }; 164. 165. inline Query 166. operator&(const Query &lhs,const Query &rhs) 167. { 168. return new AndQuery(lhs,rhs); 169. } 170. 171. inline Query 172. operator|(const Query &lhs,const Query &rhs) 173. { 174. return new OrQuery(lhs,rhs); 175. } 176. 177. inline Query 178. operator~(const Query &oper) 179. { 180. return new NotQuery(oper); 181. } 182. 183. #endif // QUERY_H_INCLUDED view sourceprint? 01. //4 in Query.cpp 02. #include "Query.h" 03. 04. set<TextQuery::line_no> 05. OrQuery::eval(const TextQuery &file) const 06. { 07. set<line_no> left = lhs.eval(file), 08. ret_lines = rhs.eval(file); 09. 10. ret_lines.insert(left.begin(),left.end()); 11. 12. return ret_lines; 13. } 14. 15. set<TextQuery::line_no> 16. AndQuery::eval(const TextQuery &file) const 17. { 18. set<line_no> left = lhs.eval(file), 19. right = rhs.eval(file); 20. 21. set<line_no> ret_lines; 22. set_intersection(left.begin(),left.end(), 23. right.begin(),right.end(), 24. inserter(ret_lines,ret_lines.begin())); 25. 26. return ret_lines; 27. } 28. 29. set<TextQuery::line_no> 30. NotQuery::eval(const TextQuery &file) const 31. { 32. set<line_no> hav_val = query.eval(file); 33. set<line_no> ret_val; 34. 35. for (line_no n = 0; n != file.size(); ++n) 36. { 37. if (hav_val.find(n) == hav_val.end()) 38. { 39. ret_val.insert(n); 40. } 41. } 42. 43. return ret_val; 44. } view sourceprint? 01. //5 in main.cpp 02. //测试数据与前面相同 03. #include <iostream> 04. #include <algorithm> 05. #include "TextQuery.h" 06. #include "Query.h" 07. 08. using namespace std; 09. 10. int main() 11. { 12. ifstream inFile("input"); 13. 14. TextQuery file; 15. file.read_file(inFile); 16. 17. Query q = Query("fiery") & Query("bird") | Query("wind"); 18. 19. cout << "Executed Query for :" << q << endl; 20. 21. typedef set<TextQuery::line_no> line_nums; 22. 23. const line_nums &locs = q.eval(file); 24. 25. cout << "match occurs " << locs.size() 26. << " times" << endl; 27. 28. line_nums::const_iterator it = locs.begin(); 29. for (; it != locs.end(); ++it) 30. { 31. cout << "\t(line " << (*it) + 1 << ") " 32. << file.text_line(*it) << endl; 33. } 34. }
解决方案
40
《C++编程思想》