c++primer里的文本查询程序扩展

来源:互联网 发布:深圳少儿编程培训 编辑:程序博客网 时间:2024/05/17 08:43

感觉这个例子很锻炼面向对象思想,所以还是写下来吧

Query_base.h

#pragma once# include"TextQuery.h"# include"QueryResult.h"# include<string>//这是一个抽象基类,具体的查询类型从中派生,所有成员都是private的class Query_base{    friend class Query;protected:    using line_no = TextQuery::line_no; //用于eval函数    virtual ~Query_base() = default;private:    //eval返回与当前Query匹配的QueryResult    virtual QueryResult eval(const TextQuery &)const = 0;    virtual std::string rep()const = 0;};

Query.h

#pragma once# include<string># include"QueryResult.h"# include"TextQuery.h"# include"Query_base.h"# include<iostream>//这是一个管理Query_base继承体系的的接口类class Query{    //这些运算符需要访问接受shared_ptr的构造函数,而该函数是私有的    friend Query operator~(const Query&);    friend Query operator|(const Query&,const Query&);    friend Query operator&(const Query&, const Query&);public:    Query(const std::string&);//构建一个新的WordQuery    //接口函数:调用对应的Query_base操作    QueryResult eval(const TextQuery&t)const;    std::string rep()const;private:    Query(std::shared_ptr<Query_base> query);    std::shared_ptr<Query_base> q;};

Query.cpp

# include"Query.h"# include"WordQuery.h"# include<string># include<iostream>QueryResult Query::eval(const TextQuery&t)const{    return q->eval(t);}std::string Query::rep()const{    return q->rep();}Query::Query(const std::string&s):q(new WordQuery(s)){}std::ostream&operator<<(std::ostream&os, const Query&query){    //Query::rep通过它的Query_base指针对rep()进行了虚调用    return os << query.rep();}Query::Query(std::shared_ptr<Query_base> query) :q(query) {}

TextQuery.h

# pragma once# include"QueryResult.h"# include<vector># include<fstream># include<memory># include<map># include<set>class QueryResult;//为了定义函数query的返回类型,这个定义是必须的class TextQuery{public:    using line_no = std::vector<std::string>::size_type;    TextQuery(std::ifstream &);    QueryResult query(const std::string &)const;private:    std::shared_ptr<std::vector<std::string>> file;     //输入文件    std::map<std::string,        std::shared_ptr<std::set<line_no>>> wm;};

TextQuery.cpp

# include"TextQuery.h"# include<vector># include<string># include<sstream># include"QueryResult.h"class QueryResult;using namespace std;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)    //对行中每个单词        {            //如果单词不在wm中,以之为下标在wm中添加一项            auto &lines = wm[word];//lines是一个sharred_ptr            if (!lines) //在我们第一次遇到这个单词时,此指针为空                lines.reset(new set < line_no>);//分配一个新的set            lines->insert(n);   //将此行号插入set中            }    }}QueryResult TextQuery::query(const string &sought)const{    //如果未找到sought,我们将返回一个指向此set的指针    static shared_ptr<set<line_no>> nodata(new set<line_no>);    //使用find而不是下标运算符来查找单词,避免将单词添加到wm中    auto loc = wm.find(sought);    if (loc == wm.end())        return QueryResult(sought, nodata, file);   //未找到    else return        QueryResult(sought, loc->second, file);}

QueryResult.h

# pragma once# include<iostream># include"TextQuery.h"# include<memory># include<set># include<vector># include<string>class QueryResult{    friend std::ostream& print(std:: ostream &, const QueryResult&);public:    using size = std::vector<std::string>::size_type;    QueryResult(std::string s,        std::shared_ptr<std::set<size>> p,        std::shared_ptr<std::vector<std::string>> f);    std::set<size>::iterator begin();    std::set<size>::iterator end();    std::shared_ptr<std::vector<std::string>> get_file();private:    std::string sought;//查询单词    std::shared_ptr<std::set<size>> lines;//出现的行号    std::shared_ptr<std::vector<std::string>> file; //输入文件};

QueryResult.cpp

# include"QueryResult.h"# include"TextQuery.h"using size = std::vector<std::string>::size_type;QueryResult::QueryResult(std::string s,    std::shared_ptr<std::set<size>> p,    std::shared_ptr<std::vector<std::string>> f):sought(s), lines(p), file(f)    {}std::set<size>::iterator QueryResult::begin(){    return this->lines->begin();}std::set<size>::iterator QueryResult::end(){    return this->lines->end();}std::shared_ptr<std::vector<std::string>> QueryResult::get_file(){    return this->file;}

WordQuery.h

#pragma once# include"Query_base.h"# include<string>class WordQuery:public Query_base{    friend class Query; //Query使用WordQuery构造函数    WordQuery(const std::string &s);    //具体的类:WordQuery将定义所有继承+而来的纯虚函数    QueryResult eval(const TextQuery&t)const;    std::string rep()const;    std::string query_word; //要查找的单词};

WordQuety.cpp

# include"WordQuery.h"WordQuery::WordQuery(const std::string &s) :query_word(s) {}//具体的类:WordQuery将定义所有继承而来的纯虚函数QueryResult WordQuery::eval(const TextQuery&t)const{    return t.query(query_word);}std::string WordQuery::rep()const{    return query_word;}

BinaryQuery.h

# pragma once# include"Query.h"# include"Query_base.h"class BinaryQuery:public Query_base{protected:    BinaryQuery(const Query &l, const Query &r, std::string s);    //抽象类:BinaryQuery不定义eval    std::string  rep()const;    Query lhs,rhs;  //右侧和左侧运算对象    std::string opSym;  //运算符的名字};

BinaryQuery.cpp

# include"BinaryQuery.h"BinaryQuery::BinaryQuery(const Query &l, const Query &r, std::string s) :    lhs(l), rhs(r), opSym(s) {}std::string  BinaryQuery::rep()const{    return "(" + lhs.rep() + " " + opSym + " " + rhs.rep() + ")";}

AndQuery.h

#pragma once# include"BinaryQuery.h"class AndQuery:public BinaryQuery{    friend Query operator&(const Query&, const Query&);    AndQuery(const Query&left, const Query&right);    //具体的类:AndQuery继承了rep并且定义了其他纯虚函数    QueryResult eval(const TextQuery&)const;};

AndQuery.cpp

# include"AndQuery.h"# include<set># include<memory># include<algorithm># include<iterator>AndQuery::AndQuery(const Query&left, const Query&right) :    BinaryQuery(left, right, "&") {}Query operator&(const Query&lhs, const Query &rhs){    return std::shared_ptr<Query_base>(new AndQuery(lhs, rhs));}QueryResult AndQuery::eval(const TextQuery&text)const{    //通过Query运算对象进行的虚调用,以获得运算对象的查询结果set    auto left = lhs.eval(text), right = rhs.eval(text);    //保存left和right的交集的set    auto ret_lines = std::make_shared<std::set<line_no>>();    //将两个范围的交集写入一个目的迭代器中    //本次调用的目的迭代器向ret添加元素    std::set_intersection(left.begin(), left.end(), right.begin(), right.end(),        inserter(*ret_lines, ret_lines->begin()));    return QueryResult(rep(), ret_lines, left.get_file());}

OrQuery.h

#pragma once# include"BinaryQuery.h"class OrQuery :public BinaryQuery{    friend Query operator|(const Query&, const Query&);    OrQuery(const Query&left, const Query&right);    //具体的类:AndQuery继承了rep并且定义了其他纯虚函数    QueryResult eval(const TextQuery&)const;};

OrQuery.cpp

# include"OrQuery.h"# include<memory># include<set># include"BinaryQuery.h"# include"Query_base.h"# include"Query.h"OrQuery::OrQuery(const Query&left, const Query&right) :    BinaryQuery(left, right, "|") {}QueryResult OrQuery::eval(const TextQuery&text)const{    //通过Query成员lhs和rhs进行的虚调用    //调用eval返回每个运算对象的QueryResult    auto right = rhs.eval(text), left = lhs.eval(text);    //将左侧运算对象的行号拷贝到结果Set中    auto ret_lines = std::make_shared<std::set<line_no>>(left.begin(), left.end());    //插入右侧运算对象所得的行号    ret_lines->insert(right.begin(), right.end());    //返回一个新的QueryResult,它表示lhs和rhs的并集    return QueryResult(rep(), ret_lines, left.get_file());} Query operator|(const Query&lhs, const Query &rhs){    return std::shared_ptr<Query_base>(new OrQuery(lhs, rhs));}

NotQuery.h

#pragma once# include"Query_base.h"# include"Query.h"class NotQuery:public Query_base{    friend Query operator~(const Query&);    NotQuery(const Query&q);    //具体的类:NotQuery将定义所有继承而来的纯虚函数    std::string rep()const;    QueryResult eval(const TextQuery&) const;    Query query;};

NotQuery.cpp

# include"NotQuery.h"# include<memory># include<set># include"QueryResult.h"class QueryResult;NotQuery::NotQuery(const Query&q) :query(q) {}std::string NotQuery::rep()const{    return "~(" + query.rep() + ")";}QueryResultNotQuery::eval(const TextQuery&text)const{    auto result = query.eval(text);    auto ret_lines=std::make_shared<std::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());}Query operator~(const Query&operand){    //return std::shared_ptr<Query_base>(new NotQuery(operand));    //等价于:    std::shared_ptr<Query_base> tmp(new NotQuery(operand));    return Query(tmp);}

先来查找单个单词,main.cpp

# include<iostream># include<fstream># include<string># include"Query.h"# include"QueryResult.h"# include"TextQuery.h"# include"WordQuery.h"using namespace std;std::ostream& print(std::ostream &, const QueryResult&);std::string make_plural(size_t i, const std::string &word, const std::string &end){    return i == 1 ? word : word + end;}int main(){    std::ifstream fin("E:\\项目\\c++\\文本查询程序2\\文本查询程序2\\file.txt");    TextQuery text(fin);    Query a1("windows");    Query a2("class");    Query b1=~a1;    Query b2 = a1&a1;    Query b3 = a1 | a1;    auto s = a1.rep();    cout << s << endl;    const auto result = a1.eval(text);    print(std::cout, result);    fin.close();    system("pause");    return 0;}std::ostream& print(std::ostream &os, const QueryResult&qr){    os << qr.sought << " occus " << qr.lines->size() << " "\        << make_plural(qr.lines->size(), "time", "s") << std::endl;    for (auto num : *qr.lines)        os << "\t(line " << num + 1 << ")\t" << *(qr.file->begin() + num) << std::endl;    return os;}

查找单词windows:
这里写图片描述

接下来查找没有单词a1的:
这里写图片描述

查找同时出现a1和a2:
这里写图片描述
查找出现a1或a2:
这里写图片描述

0 0
原创粉丝点击