maoxianmenlian的个人博客分享 http://blog.sciencenet.cn/u/maoxianmenlian

博文

《C++ Primer》第十五章文本查询示例

已有 3674 次阅读 2013-8-28 17:30 |个人分类:C++|系统分类:科研笔记

对Query中句柄的使用没看明白,已经耗了一天了,不能再看这个了,难度太高,找工作估计用不到。


源代码:

#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <set>
#include <map>
#include<algorithm>
using namespace std;

class TextQuery;
class Query;
class Query_base;
class WordQuery;
class NotQuery;
class BinaryQuery;
class AddQuery;
class OrQuery;

class TextQuery
{
public:
   typedef vector<string>::size_type line_no;
   typedef std::string::size_type str_size;
   void read_file(ifstream &is)
   {
       store_file(is);
       build_map();
   }

   set<line_no> run_query(const string&) const;
   string text_line(line_no) const;
   str_size size() const
   {
       return lines_of_text.size();
   }
   
private:
   void store_file(ifstream&);
   void build_map();
   std::vector<string> lines_of_text;
   std::map<string, set<line_no>> word_map;
};

string make_plural(size_t ctr,const string &word,const string &ending)
{
   return (ctr==1)?word:word+ending;
}

void print_results(const set<TextQuery::line_no>& locs, const TextQuery &file)
{
   // report no matches
   if (locs.empty()) {
       cout << "nSorry. There are no entries for your query."
            << "nTry again." << endl;
       return;
   }

   // if the word was found, then print count and all occurrences
   set<TextQuery::line_no>::size_type size = locs.size();
   cout << "match occurs "
        << size << (size == 1 ? " time:" : " times:") << endl;

   // print each line in which the word appeared
   set<TextQuery::line_no>::const_iterator it = locs.begin();
   for ( ; it != locs.end(); ++it) {
       cout << "t(line "
            // don't confound user with text lines starting at 0
            << (*it) + 1 << ") "
            << file.text_line(*it) << endl;
   }
}
ifstream& open_file(ifstream &in, const string &file)
{
   in.close();
   in.clear();
   in.open(file.c_str());
   return in;
}

void TextQuery::store_file(ifstream &is)
{
   string textline;
   while(getline(is,textline))
       lines_of_text.push_back(textline);
}

void TextQuery::build_map()
{
   for(line_no line_num=0;line_num!=lines_of_text.size();++line_num)
   {
       istringstream line(lines_of_text[line_num]);
       string word;
       while(line>>word)
       {
           word_map[word].insert(line_num);
       }
   }
}

set<TextQuery::line_no> TextQuery::run_query(const string &query_word) const
{
   map<string,set<line_no> >::const_iterator loc=word_map.find(query_word);

   if(loc==word_map.end())
       return set<line_no>();
   else
       return loc->second;
}

string TextQuery::text_line(line_no line) const
{
   if(line<lines_of_text.size())
       return lines_of_text[line];
   throw out_of_range("line number out of range");
}

class Query_base
{
   friend class Query;
protected:
   typedef TextQuery::line_no line_no;
   virtual ~Query_base(){}
private:
   virtual std::set<line_no> eval(const TextQuery&) const=0;
   virtual std::ostream& display(std::ostream& = std::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 std::string&);
   Query(const Query &c):q(c.q),use(c.use)
   {
       ++*use;
   }
   ~Query()
   {
       decr_use();
   }
   Query& operator=(const Query&);
   std::set<TextQuery::line_no> eval(const TextQuery &t) const
   {
       return q->eval(t);
   }
   std::ostream &display(std::ostream &os) const
   {
       return q->display(os);
   }
private:
   Query(Query_base *query):q(query),use(new std::size_t(1))
   {
   }
   Query_base *q;
   std::size_t *use;
   void decr_use()
   {
       if(--*use==0)
       {
           delete q;
           delete use;
       }
   }
};

inline Query& Query::operator=(const Query &rhs)
{
   ++*rhs.use;
   decr_use();
   q = rhs.q;
   use = rhs.use;
   return *this;
}

inline std::ostream& operator<<(std::ostream &os,const Query &q)
{
   return q.display(os);
}

class BinaryQuery:public Query_base
{
protected:
   BinaryQuery(Query left,Query right,std::string op):lhs(left),rhs(right),oper(op)
   {
   }
   std::ostream& display(std::ostream &os) const
   {
       return os<<"("<<lhs<<" "<<oper<<" "<<rhs<<")";
   }
   const Query lhs,rhs;
   const std::string oper;
};

class AndQuery:public BinaryQuery
{
   friend Query operator &(const Query&,const Query&);
   AndQuery(Query left,Query right):BinaryQuery(left,right,"&")
   {
   }
   std::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,"|")
   {
   }
   std::set<line_no> eval(const TextQuery&) const;
};

class WordQuery:public Query_base
{
   friend class Query;
   WordQuery(const std::string &s):query_word(s)
   {
   }
   std::set<line_no> eval(const TextQuery &t) const
   {
       return t.run_query(query_word);
   }
   std::ostream& display(std::ostream &os) const
   {
       return os<<query_word;
   }
   std::string query_word;
};

inline Query::Query(const std::string &s): q(new WordQuery(s)),
                              use(new std::size_t(1)) { }


class NotQuery:public Query_base
{
   friend Query operator ~(const Query &);
   NotQuery(Query q):query(q){}
   std::set<line_no> eval (const TextQuery&) const;
   std::ostream& display(std::ostream &os) const
   {
       return os<<"~("<<query<<")";
   }
   const Query query;
};

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



set<TextQuery::line_no> OrQuery::eval(const TextQuery&file)const
{
   set<line_no> right=rhs.eval(file),ret_lines=lhs.eval(file);
   ret_lines.insert(right.begin(),right.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<TextQuery::line_no> has_val=query.eval(file);
   set<line_no> ret_lines;

   for(TextQuery::line_no n=0;n!=file.size();++n)
       if(has_val.find(n)==has_val.end())
           ret_lines.insert(n);
   return ret_lines;
}

//int main(int argc,char **argv)
//{
//    ifstream infile;
//    if(argc<2 || !open_file(infile, argv[1]))
//    {
//        cerr<<"No input file!"<<endl;
//        return EXIT_FAILURE;
//    }
//
//    TextQuery tq;
//    tq.read_file(infile);
//    while(true)
//    {
//        cout<<"enter word to look for, or q to quit: ";
//        string s;
//        cin>>s;
//        if(!cin || s=="q")
//            break;
//        set<TextQuery::line_no> locs=tq.run_query(s);
//        print_results(locs, s, tq);
//    }
//    return 0;
//}

TextQuery build_textfile(const string &filename)
{
   // get a file to read from which user will query words
   ifstream infile;
   if (!open_file(infile, filename)) {
       cerr << "No input file!" << endl;
       return TextQuery();
   }

   TextQuery ret;
   ret.read_file(infile);  // builds query map
   return ret;  // builds query map
}
bool get_word(string &s1)
{
   cout << "enter a word to search for, or q to quit: ";
   cin >> s1;
   if (!cin || s1 == "q") return false;
   else return true;
}
bool get_words(string &s1, string &s2)
{

   // iterate with the user: prompt for a word to find and print results
   cout << "enter two words to search for, or q to quit: ";
   cin  >> s1;

   // stop if hit eof on input or a "q" is entered
   if (!cin || s1 == "q") return false;
   cin >> s2;
   return true;
}
int main(int, char **argv)
{
   // gets file to read and builds map to support queries
   TextQuery file = build_textfile(argv[1]);

   // iterate with the user: prompt for a word to find and print results
   do {
       string sought1, sought2;
       // stop if hit eof on input or a "q" is entered
       if (!get_words(sought1, sought2)) break;
   
       // find all the occurrences of the requested string
       Query andq = Query(sought1) & Query(sought2);
       set<TextQuery::line_no> locs = andq.eval(file);
       cout << "nExecuted query: " << andq << endl;
       // report matches
       print_results(locs, file);
   
       locs = Query(sought1).eval(file);
       cout << "nExecuted query: " << Query(sought1) << endl;
       // report matches
       print_results(locs, file);
   
       locs = Query(sought2).eval(file);
       cout << "nExecuted query: " << Query(sought2) << endl;
       // report matches
       print_results(locs, file);
   } while(true);
   return 0;
}

//int main(int, char **argv)
//{
//    // gets file to read and builds map to support queries
//    TextQuery file = build_textfile(argv[1]);
//
//    // iterate with the user: prompt for a word to find and print results
//    while (true) {
//        string sought1, sought2, sought3;
//        if (!get_words(sought1, sought2)) break;
//        cout << "nenter third word: " ;
//        cin  >> sought3;
//        // find all the occurrences of the requested string
//        Query q = Query(sought1) & Query(sought2)
//                             | Query(sought3);
//
//        cout << "nExecuting Query for: " << q << endl;
//        const set<TextQuery::line_no> locs = q.eval(file);
//        // report matches
//        print_results(locs, file);
//     }
//     return 0;
//}



https://blog.sciencenet.cn/blog-791354-720413.html

上一篇:重学C++
下一篇:一道考察重载、多态、继承的经典笔试题
收藏 IP: 125.71.200.*| 热度|

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-12-23 23:04

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部