C++ primer 文本查询程序 Query

来源:互联网 发布:造梦西游刷点卷软件 编辑:程序博客网 时间:2024/04/30 15:52

C++ primer 文本查询程序,面向对象的实现,有很多值得学习的知识点。

整理了代码如下,使用VS2010,g++编译通过:


#include <map>#include <set>#include <vector>#include <string>#include <algorithm>#include <iterator>#include <istream>#include <sstream>  //istringstreamusing std::istringstream;using std::map;using std::set;using std::vector;using std::string;#include <iostream>using std::ostream;using std::cout;using std::cin;using std::cerr;using std::endl;#include <fstream>using std::getline;using std::ifstream;/** * @brief The TextQuery class */class TextQuery{public:    typedef vector<string>::size_type line_no;    void read_file(std::ifstream &is)    {        store_file(is);        build_map();    }    set<line_no> run_query(string &) const;    string text_line(line_no) const;    line_no size() const   //the total lines num    {        return lines_of_text.size();    }private:    void store_file(std::ifstream &);    void build_map();    vector<string> lines_of_text;    map<string,set<line_no> > word_map;};set<TextQuery::line_no> TextQuery::run_query(string &query_word) const{    map<string,set<line_no> >::const_iterator iter = word_map.find(query_word);    if ( iter != word_map.end() )    {        return iter->second;    }    return set<line_no>();}string TextQuery::text_line(line_no line) const{    return lines_of_text[line];}void TextQuery::store_file(std::ifstream &is){    string textline;    while ( getline(is,textline) )    {        lines_of_text.push_back(textline);    }}void TextQuery::build_map(){    line_no line_num = 0;    for ( ; 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);        }    }}/** * @brief The Query_base class */class Query_base{    friend class Query;protected:    virtual ~Query_base()    {    }private:    virtual set<TextQuery::line_no> eval(const TextQuery &) const = 0;    virtual ostream & display(ostream &os = 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 string &word); //builds a new wordQuery    //copy control to manage pointers and counting    Query(const Query &c):q(c.q),use(c.use)    {        ++*use;    }    ~Query()    {        decr_use();    }    Query &operator=(const Query &query)    {        q = query.q;        ++*use;        return *this;    }    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 ostream & operator<<(ostream &os,const Query &query)   //why needed const for Query &??{    query.display(os);    return os;}/** * @brief The WordQuery class */class WordQuery : public Query_base{    friend class Query;    WordQuery(const string &s):query_word(s)    {    }    set<TextQuery::line_no> eval(const TextQuery &t) const    {        return t.run_query((string &)query_word);   //why needed const?    }    ostream & display(ostream &os = std::cout ) const;    string query_word;};ostream & WordQuery::display(ostream &os) const{    return os<<query_word;}//Query constructor!! we can't define before the WordQuery class finishQuery::Query(const string &word) //builds a new wordQuery{    q = new WordQuery(word);    use = new std::size_t(1);}/** * @brief The NotQuery class */class NotQuery :public Query_base{    friend Query operator~(const Query &);    NotQuery(const Query &q):query(q)    {    }    set<TextQuery::line_no> eval(const TextQuery &) const;   //becareful the last const,if you forget to add it in the implement,it overloads and bug    ostream & display(ostream &os) const;    const Query query;   //const is ok,when you initianize in the constructor};set<TextQuery::line_no> NotQuery::eval(const TextQuery &file) const{    set<TextQuery::line_no> has_val = query.eval(file);    set<TextQuery::line_no> ret_lines;    TextQuery::line_no n = 0;    for ( ; n != file.size() ; ++n )    {        if ( has_val.find(n) == has_val.end() )        {            ret_lines.insert(n);        }    }    return ret_lines;}ostream & NotQuery::display(ostream &os) const{    return os<<"~("<<query<<")";}/** * @brief The BinaryQuery class */class BinaryQuery : public Query_base{protected:   //can't not be private    BinaryQuery(Query left,Query right,string op):lhs(left),rhs(right),oper(op)    {    }    ostream & display(ostream &os = std::cout ) const    {        return os<<"("<<lhs<<" "<<oper<<" "<<rhs<<")";    }    Query lhs,rhs;    string oper;   //& |};/** * @brief The AndQuery class */class AndQuery : public BinaryQuery{    friend Query operator&(const Query &,const Query &);    AndQuery(const Query &left,const Query &right):BinaryQuery(left,right,"&")    {    }    set<TextQuery::line_no> eval(const TextQuery &) const;};set<TextQuery::line_no> AndQuery::eval(const TextQuery &file) const{    set<TextQuery::line_no> left = lhs.eval(file),    right = rhs.eval(file);    set<TextQuery::line_no> ret_lines;    set_intersection(left.begin(),left.end(),right.begin(),right.end(),inserter(ret_lines,ret_lines.begin()));    return ret_lines;}/** * @brief The OrQuery class */class OrQuery : public BinaryQuery{    friend Query operator|(const Query &,const Query &);    OrQuery(const Query lq,const Query rq):BinaryQuery(lq,rq,"|")    {    }    set<TextQuery::line_no> eval(const TextQuery &) const;};set<TextQuery::line_no> OrQuery::eval(const TextQuery &file) const{    set<TextQuery::line_no> right = lhs.eval(file),    ret_lines = rhs.eval(file);    ret_lines.insert(right.begin(),right.end());    return ret_lines;}Query operator~(const Query &query){    return new NotQuery(query);}Query operator|(const Query &lhr,const Query &rhr){    return new OrQuery(lhr,rhr);}Query operator&(const Query &lhr,const Query &rhr){    return new AndQuery(lhr,rhr);}void print_result(const set<TextQuery::line_no> &locs,const TextQuery &file){    typedef set<TextQuery::line_no> line_nums;    line_nums::const_iterator iter = locs.begin();    for( ; iter != locs.end() ; iter++ )    {        cout<<"\tline"<<(*iter)+1<<")"<<file.text_line(*iter)<<endl;    }}bool open_file(ifstream &is,char *filename){    if ( is.is_open() )    {        is.close();    }    is.open(filename);    if ( is.is_open() == true )    {        return true;    }    return false;}int main(){    ifstream infile;    if ( !open_file(infile,(char *)"TextQuery.txt"))    {        cerr<<"No input file!"<<endl;        return -1;    }    TextQuery tq;    tq.read_file(infile);    //Query q = Query("I") & Query("like") | Query("you");    //Query q = Query("you") & Query("like");    Query q = Query("I") & Query("like");    set<TextQuery::line_no> res = q.eval(tq);    q.display(cout);    cout<<endl;    print_result(res,tq);}

测试文件为 TextQuery.txt ,内容如下,

I like you and hope you like me!
But you don't like me,I know that,I am so sad!
One day,will you like me?




0 0
原创粉丝点击