c++primer文本查询系统

来源:互联网 发布:上海证券软件下载 编辑:程序博客网 时间:2024/05/02 02:27

以下是c++pirmer的文本查询系统再探的源码,基本部分没有做什么修改。编译环境为c-free5.0,已编译通过。
这里提几个注意事项:
1.使用c++11特性的时候,在编译环境里增加指令-std=c++11.代码中出现的shared_ptr、make_ptr原本是boost库中的内容,已经被吸收到了c++标准库中,引用头文件memory即可。
2.如果在做15.34的练习的时候,编译会出现Link error undefined reference to “vtable for XXX”的错误,这是因为虚函数在链接的时候还没有函数体,这时候还没有定义eval函数。举个例子比方下面的类,编译就会出错。

class Base
{
virtual void f() = 0;
}
class Derived : public Base
{
void f();
}

解决办法是在类外定义一个函数体即可。

void Derived::f(){}

3.第三个也不算注意事项啦,程序需要前面一些练习作为前提,这里已经完成了。
另外,在使用line_no这个属性的时候,提前声明一下,似乎书中遗漏了这行代码,会出现未定义的错误。

#include <string>#include <vector>#include <iostream>#include <fstream>#include <sstream>#include <set>#include <map>#include <memory>#include <algorithm> using namespace std;string make_plural(size_t ctr,const string& word,const string &end){    return (ctr==1)?word:word+end;}class QueryResult;class TextQuery{    public:        using line_no=vector<string>::size_type;        TextQuery(ifstream&);        QueryResult query(const string&) const;    private:        shared_ptr<vector<string>> file;        map<string,shared_ptr<set<line_no>>> wm;};TextQuery::TextQuery(ifstream& is):file(new vector<string>){    string text;    while(getline(is,text)){        file->push_back(text);        int n=file->size()-1;        istringstream line(text);        string word;        while(line>>word){            auto &lines=wm[word];            if(!lines){                lines.reset(new set<line_no>);              }            lines->insert(n);        }            }};class QueryResult{    friend ostream& print(ostream&,const QueryResult&);    public:        using line_no=TextQuery::line_no;        using ResultIter=set<line_no>::iterator;        QueryResult(string s,                    shared_ptr<set<line_no> > p,                    shared_ptr<vector<string>> f):            sought(s),lines(p),file(f){}        shared_ptr<vector<string>> get_file()const {            return file;        }        ResultIter begin()const {            return lines->begin();        }        ResultIter end() const{            return lines->end();        }    private:        string sought;        shared_ptr<set<line_no> > lines;        shared_ptr<vector<string>> file;};QueryResultTextQuery::query(const string&sought) const{    static shared_ptr<set<line_no>> nodata(new set<line_no>);    auto loc=wm.find(sought);    if(loc==wm.end())        return QueryResult(sought,nodata,file);    else        return QueryResult(sought,loc->second,file);};ostream &print(ostream& os,const QueryResult &qr){    os<<qr.sought<<"occur "<<qr.lines->size()<<" "        <<make_plural(qr.lines->size(),"times","s")<<endl;    for(auto num:*qr.lines){        os<<"\t(line"<<num+1<<")"            <<*(qr.file->begin()+num)<<endl;    }    return os;}class Query_base{    friend class Query;    protected:        using line_no=TextQuery::line_no;        virtual ~Query_base();     private:        virtual QueryResult eval(const TextQuery&)const =0;        virtual string rep()const=0;} ;Query_base::~Query_base(){}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&);        QueryResult eval(const TextQuery &t)const{            return q->eval(t);            cout<<"WordQuery eval"<<endl;        }        string rep()const{            cout<<"Query rep"<<endl;            return q->rep();        }    private:        Query(shared_ptr<Query_base> query):q(query){        }        shared_ptr<Query_base> q;};ostream &operator<<(ostream &os,const Query &query){    return os<<query.rep();}class WordQuery:public Query_base{    friend class Query;    WordQuery(const string &s):query_word(s){            cout<<"WordQuery construct "<<s<<endl;    }    QueryResult eval(const TextQuery &t) const{        cout<<"WordQuery eval"<<endl;        return t.query(query_word);    }    string rep()const{        cout<<"WordQuery rep"<<endl;        return query_word;    }    string query_word;};inline Query::Query(const string &s):q(new WordQuery(s)){    cout<<"Query construct"<<s<<endl;}class NotQuery:public Query_base{    friend Query operator~(const Query &);    NotQuery(const Query&q):query(q){        cout<<"NotQuery construct"<<endl;           }    string rep()const{        return "~("+query.rep()+")";    }    QueryResult eval(const TextQuery&) const;       Query query;    };inline Query operator~(const Query &operand){    return shared_ptr<Query_base>(new NotQuery(operand));}QueryResultNotQuery::eval(const TextQuery& text)const{    auto result=query.eval(text);    auto ret_lines=make_shared<set<line_no>>();    auto beg=result.begin(),end=result.end();    auto sz=result.get_file()->size();    for(size_t n=0;n!=sz;++n){        if(beg==end||*beg!=n)            ret_lines->insert(n);        else if(beg!=end)            ++beg;    }    return QueryResult(rep(),ret_lines,result.get_file());}class Binary_Query:public Query_base{    protected:        Binary_Query(const Query &l,const Query &r,string s):            lhs(l),rhs(r),opSym(s){                cout<<"Binary_Query construct"<<s<<endl;                }        string rep()const{            cout<<"Binary_Query rep"<<endl;            return "("+lhs.rep()+" "                      +opSym+" "                      +rhs.rep()+")";        }    Query lhs,rhs;    string opSym;};class AndQuery:public Binary_Query{    friend Query operator&(const Query&,const Query &);    AndQuery(const Query& l,const Query &r):            Binary_Query(l,r,"&"){                cout<<"AndQuery construct"<<endl;            }    QueryResult eval(const TextQuery&) const;};QueryResult AndQuery::eval(const TextQuery& text) const{    cout<<"AndQuery eval"<<endl;    auto left=lhs.eval(text),right=rhs.eval(text);    auto ret_lines=make_shared<set<line_no>>();    set_intersection(left.begin(),left.end(),                     right.begin(),right.end(),                     inserter(*ret_lines,ret_lines->begin()));    return QueryResult(rep(),ret_lines,left.get_file());}inline Query operator&(const Query &lhs,const Query &rhs){    return shared_ptr<Query_base>(new AndQuery(lhs,rhs));}class OrQuery:public Binary_Query{    friend Query operator|(const Query&,const Query &);    OrQuery(const Query& l,const Query &r):            Binary_Query(l,r,"|"){ cout<<"OrQuery construct"<<endl; }    QueryResult eval(const TextQuery&) const;};inline Query operator|(const Query &lhs,const Query &rhs){    return shared_ptr<Query_base>(new OrQuery(lhs,rhs));}QueryResult OrQuery::eval(const TextQuery& text) const{    cout<<"OrQuery eval"<<endl;    auto right=rhs.eval(text),left=lhs.eval(text);    auto ret_lines=        make_shared<set<line_no>>(left.begin(),left.end());    ret_lines->insert(right.begin(),right.end());    return QueryResult(rep(),ret_lines,left.get_file());}int main(){    Query q=Query("fiery")&Query("bird")|Query("wind");    cout<<q;    return 0;}
0 0
原创粉丝点击