STL,Template,继承,多态的例子

  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 }
posted @ 2012-11-01 21:13  苍术厚朴  阅读(653)  评论(0编辑  收藏  举报