1 //使用map结构进行单词的转换,第一个参数为提供转换格式的文件,第二个参数为输入文件 2 #include <iostream> 3 #include <map> 4 #include <fstream> 5 #include <sstream> 6 #include <string> 7 using namespace std; 8 9 int main( int argc, char **argv) 10 { 11 map<string,string> trans_map; 12 string key, value; 13 if( argc != 3) 14 throw runtime_error("wrong number of arguments"); 15 ifstream map_file; 16 map_file.open(argv[1]); 17 if (!map_file) 18 throw runtime_error("no transformation file"); 19 while ( map_file >> key >> value) 20 trans_map.insert(make_pair(key, value)); 21 22 ifstream input; 23 input.open(argv[2]); 24 if( !input) 25 throw runtime_error("no input file"); 26 string line; 27 while( getline( input, line)) 28 { 29 istringstream stream(line); 30 string word; 31 bool firstword = true; 32 while( stream >> word) 33 { 34 map<string, string>::const_iterator map_it = trans_map.find(word); 35 if ( map_it != trans_map.end()) 36 word = map_it->second; 37 if( firstword) 38 firstword = false; 39 else 40 cout << " "; 41 cout << word; 42 } 43 cout << endl; 44 } 45 return 0; 46 } 47 48 //容器的综合应用:文本查询程序 49 #include <iostream> 50 #include <string> 51 #include <fstream> 52 #include <sstream> 53 #include <map> 54 #include <set> 55 #include <vector> 56 #include <algorithm> 57 #include <iterator> 58 using namespace std; 59 60 class TextQuery 61 { 62 public: 63 typedef vector<string>::size_type line_no; 64 void read_file( ifstream &is) 65 { 66 store_file(is); 67 build_map(); 68 } 69 set<line_no> run_query(const string&) const; 70 string text_line(line_no) const; 71 line_no size() const 72 { 73 return (line_no)lines_of_text.size(); 74 } 75 private: 76 void store_file( ifstream &); 77 void build_map(); 78 vector<string> lines_of_text; //文件中的每一行是该vector对象的一个元素 79 map <string, set<line_no> >word_map; //将单词的行号存入set对象中。使用set可以保证每行只有一个条目,而且自动按升序排列 80 //使用一个map容器将每个单词与一个set容器关联起来,该set对象记录此单词所在行号 81 }; 82 //存储输入文件 83 void TextQuery::store_file(ifstream &is) 84 { 85 string textline; 86 while( getline(is,textline) ) 87 lines_of_text.push_back(textline); 88 } 89 //建立单词map容器 90 void TextQuery::build_map() 91 { 92 for (line_no line_num=0; line_num != lines_of_text.size(); ++line_num) 93 { 94 istringstream line(lines_of_text[line_num]); 95 string word; 96 while ( line >> word) 97 word_map[word].insert(line_num); 98 } 99 } 100 //支持查询 101 set<TextQuery::line_no> TextQuery::run_query(const string &query_word) const 102 { 103 map<string, set<line_no> >::const_iterator loc = word_map.find(query_word); 104 if ( loc == word_map.end()) 105 return set<line_no>(); 106 else 107 return loc->second; 108 } 109 110 //run_query 返回值的使用 111 string TextQuery::text_line(line_no line) const 112 { 113 if( line < lines_of_text.size()) 114 return lines_of_text[line]; 115 throw out_of_range("line number out of range"); 116 } 117 118 //输出结果 119 void print_results(const set<TextQuery::line_no> & locs,const string& sought, const TextQuery &file) 120 { 121 typedef set<TextQuery::line_no> line_nums; 122 line_nums::size_type size = locs.size(); 123 cout << "\n" <<sought << " occurs" << size <<" " <<endl; 124 line_nums::const_iterator it = locs.begin(); 125 for ( ; it != locs.end(); ++it) 126 { 127 cout <<"\t(line"<< (*it)+1<<") " 128 << file.text_line(*it) <<endl; 129 } 130 } 131 132 int main( int argc, char **argv) 133 { 134 ifstream infile; 135 infile.open(argv[1]); 136 if( !infile) 137 throw runtime_error("no input file"); 138 TextQuery tq; 139 tq.read_file(infile); 140 while(true) 141 { 142 cout <<"enter word to look for, or q to quit; "; 143 string s; 144 cin >> s; 145 if ( !cin || s == "q") 146 break; 147 set<TextQuery::line_no> locs = tq.run_query(s); 148 print_results(locs,s,tq); 149 } 150 return 0; 151 } 152 153 //文本查询面向对象的实现,可支持与,或,非查询,使用的是继承和动态绑定 154 //查询类的抽象基类 155 class Query_base 156 { 157 friend class Query; // 友元类,可以访问Query_base成员函数和变量 158 protected: 159 typedef TextQuery::line_no line_no; 160 virtual ~Query_base() { } //虚析构函数 161 private: 162 virtual set<line_no> eval(const TextQuery&) const =0; //纯虚函数,每个派生类都有自己的实现 163 virtual ostream& display( ostream & = cout) const =0; 164 }; 165 166 //用户计数的句柄类,它指向Query_base派生类的对象 167 class Query{ 168 friend Query operator ~(const Query &); //友元函数重载运算符 169 friend Query operator | (const Query &, const Query &); 170 friend Query operator & (const Query &, const Query &); 171 friend ostream & operator <<(ostream &os,const Query &q) 172 { 173 return q.display(os); 174 } 175 public: 176 Query( const string&); 177 Query(const Query &c): q(c.q), use(c.use) 178 { ++*use;} 179 ~Query() { decr_use(); } 180 Query & operator =(const Query &); 181 set<TextQuery::line_no> eval(const TextQuery &t) const 182 { 183 return q->eval(t); 184 } 185 ostream &display( ostream &os) const 186 { 187 return q->display(os); 188 } 189 private: 190 Query(Query_base * query): q(query), use(new size_t(1)) 191 { } 192 Query_base *q; //基类指针,可以指向派生类对象,从而实现多态 193 size_t *use; 194 void decr_use() 195 { 196 if( --*use == 0) 197 { 198 delete q; 199 delete use; 200 } 201 } 202 }; 203 204 inline Query operator & (const Query &lhs, const Query &rhs) 205 { 206 return new AndQuery(lhs, rhs); 207 } 208 inline Query operator | (const Query &lhs, const Query &rhs) 209 { 210 return new OrQuery(lhs,rhs); 211 } 212 inline Query operator ~(const Query &oper) 213 { 214 return new NotQuery(oper); 215 } 216 217 218 class WordQuery: public Query_base 219 { 220 friend class Query; 221 WordQuery(const string &s):query_word(s){ } 222 set<line_no> eval(const TextQuery &t ) const 223 { 224 return t.run_query(query_word); 225 } 226 ostream& display( ostream &os ) const 227 { 228 return os << query_word; 229 } 230 string query_word; 231 }; 232 233 234 class NotQuery: public Query_base 235 { 236 friend Query operator ~ (const Query &); 237 NotQuery(Query q): query(q) { } 238 set<line_no> eval( const TextQuery &) const; 239 ostream & display(ostream &os) const 240 { 241 return os << "~(" << query << ")"; 242 } 243 const Query query; 244 }; 245 246 set<TextQuery::line_no> NotQuery::eval(const TextQuery & file) const 247 { 248 set<line_no> has_val = query.eval(file); 249 set<line_no> ret_lines; 250 for ( line_no n=0; n != file.size(); ++n) 251 if( has_val.find(n) == has_val.end() ) 252 ret_lines.insert(n); 253 return ret_lines; 254 } 255 256 class BinaryQuery: public Query_base 257 { 258 protected: 259 BinaryQuery(Query left, Query right, string op) : lhs(left), rhs(right), oper(op) 260 { } 261 ostream& display( ostream &os) const 262 { 263 return os << "(" << lhs << " " << oper << " " 264 <<rhs << ")"; 265 } 266 const Query lhs, rhs; 267 const string oper; 268 }; 269 270 class AndQuery: public BinaryQuery 271 { 272 friend Query operator& (const Query&,const Query&); 273 AndQuery(Query left, Query right) : BinaryQuery(left,right,"&") { } 274 set<line_no> eval(const TextQuery &) const; 275 }; 276 277 set<TextQuery::line_no> AndQuery::eval(const TextQuery & file) const 278 { 279 set<line_no> left = lhs.eval(file), right = rhs.eval(file); 280 set<line_no> ret_lines; 281 set_intersection(left.begin(), left.end(), 282 right.begin(), right.end(), 283 inserter(ret_lines, ret_lines.begin() )); 284 return ret_lines; 285 } 286 287 class OrQuery : public BinaryQuery 288 { 289 friend Query operator|(const Query&, const Query&); 290 OrQuery(Query left,Query right) : BinaryQuery(left,right,"|") { } 291 set<line_no> eval(const TextQuery &) const; 292 }; 293 294 set<TextQuery::line_no> OrQuery::eval( const TextQuery &file) const 295 { 296 set<line_no> right = rhs.eval(file), 297 ret_lines = lhs.eval(file); 298 ret_lines.insert(right.begin(), right.end() ); 299 return ret_lines; 300 } 301 302 303 //完整的模版Queue类 304 template< class Type> class Queue; 305 template <class T> ostream& operator << ( ostream &, const Queue<T>&); 306 template <class Type> 307 //队列中元素 308 class QueueItem{ 309 public: 310 friend class Queue<Type>; //声明为友元类 311 friend ostream & operator << <Type> ( ostream&, const Queue<Type>&); 312 QueueITem(const Type &t) : item(t), next(0) { } 313 Type item; 314 QueueItem *next; 315 }; 316 317 //支持具体操作的队列类 318 template<class Type> 319 class Queue 320 { 321 friend ostream & operator << <Type> (ostream &, const Queue<Type> &); 322 public: 323 Queue( ): head(0),tail(0) { } 324 template<class It> 325 Queue(It beg, It end): head(0), tail(0) { copy_elems(beg,end); } 326 Queue(const Queue &Q) : head(0), tail(0) { copy_elems(Q); } 327 Queue& operator = (const Queue&); 328 ~Queue( ) { destroy( ); } 329 template<class Iter> void assign(Iter, Iter); 330 Type & front( ) { return head->item; } 331 const Type &front() const { return head->item; } 332 void push(const Type &); 333 void pop( ); 334 bool empty( ) const { 335 return head == 0; 336 } 337 private: 338 QueueItem<Type> *head; 339 QueueItem<Type> *tail; 340 void destroy(); 341 void copy_elems(const Queue&); 342 template <class Iter> void copy_elems(Iter, Iter); 343 }; 344 345 template <class Type> 346 void Queue<Type>::destroy() 347 { 348 while ( !empty() ) 349 pop(); 350 } 351 352 template<class Type> 353 void Queue<Type>::pop() 354 { 355 QueueItem<Type> *p = head; 356 head = head->next; 357 delete p; 358 } 359 360 template<class Type> 361 void Queue<Type>::push( const Type &val) 362 { 363 QueueItem<Type> *pt = new QueueItem<Type>(val); 364 if(empty()) 365 head = tail = pt; 366 else 367 { 368 tail ->next = pt; 369 tail = pt; 370 } 371 } 372 373 template<class Type> 374 void Queue<Type>::copy_elems( const Queue &orig) 375 { 376 for ( QueueItem<Type> *pt = orig.head; pt; pt = pt->next) 377 push( pt->item); 378 } 379 380 381 382 //定义泛型句柄类 383 template <class T> 384 class Handle 385 { 386 public: 387 Handle(T *p=0) : ptr(p), use(new size_t(1) ) { } //构造函数 388 T & operator *(); //重载运算符 389 T * operator ->(); 390 const T& operator *() const; 391 Handle( const Handle & h) : ptr(h.ptr), use(h.use) //复制构造函数 392 { ++*use;} 393 Handle & operator = (const Handle&); //赋值函数 394 ~Handle() { rem_ref(); } 395 private: 396 T* ptr; //原始指针 397 size_t *use; //使用次数 398 void rem_ref() //删除操作 399 { 400 if( --*use ==0) 401 { 402 delete ptr; 403 delete use; 404 } 405 } 406 }; 407 408 template <class T> 409 inline Handle<T> & Handle<T>::operator=( const Handle &rhs) 410 { 411 ++*rhs.use; 412 rem_ref(); 413 ptr = rhs.ptr; 414 use = rhs.use; 415 return *this; 416 } 417 418 template<class T> 419 inline T& Handle<T>::operator*() 420 { 421 if ( ptr) return *ptr; 422 throw runtime_error("dereference of unbound Handle"); 423 } 424 425 template<class T> 426 inline T* Handle<T>::operator->() 427 { 428 if( ptr ) return ptr; 429 throw runtime_error("access through unbound handle"); 430 }