C++primer学习:面向对象程序设计(5):再探文本查询程序
来源:互联网 发布:围墙设计图纸含数据 编辑:程序博客网 时间:2024/05/23 00:56
这一节初步探讨了如何设计一个继承类体系。
为我们前面所写的文本探测程序添加以下功能:
(1):可以将查询结果进行|,&,~的运算.运算的优先级按照C++规定的表达式来进行.如Query(“hair”)|Query(“bird”);
(2) : 添加一个历史系统,能够查询前面的进行的某个查询.并可以在其中增加内容并与其他查询组合.
(3):允许用户在查询的时候做出限制,从给定范围中挑出匹配的行显示.
这个体系的设计相对比较复杂,Textquery类负责进行基础的读入文件,Queryresult类负责保存结果.而我们重新定义一个继承体系Query_base继承体系,用Wordquery类,AndQuery类,OrQuery类负责保存信息.eval()函数负责解析结果,rep()函数负责打印查询的单词逻辑表达式.用Query类作为一个体系的接口类,掩盖整个体系,同时也减少用户操作难度.
同时对一些边界条件进行了检测,防止出错.
#ifndef Query_base_01#define Query_base_01#include "Textquery.h"#include "iterator"#include "memory"using namespace std;/************抽象基类query_base********************/class Query;class Query_base{ friend Query& history_query(size_t n); friend class Query;//通过该友元访问eval,rep函数public: static vector<shared_ptr<Query>> history;private: virtual QueryResult eval(const Textquery&)const = 0;//纯虚函数 /******************重载这个虚函数,接受限制范围的行数******************/ virtual QueryResult eval(const Textquery&,size_t,size_t)const; virtual string rep()const = 0;protected: Query_base() = default;};/***************重载eval*****************/QueryResult Query_base::eval(const Textquery& t, size_t min, size_t max)const{ auto res = eval(t); auto dest = make_shared<set<size_t>>(); remove_copy_if(res.begin(), res.end(), inserter(*dest, (*dest).begin()), [&](size_t q){ return (q<min || q>max); }); return QueryResult(rep(), res.get_file(), dest);}vector<shared_ptr<Query>>Query_base::history {shared_ptr<Query>()};/********定义一个接口类 Query,简化用户操作的复杂度,也可以减少类设计时的一些复杂度********/class Query{ friend Query operator~(const Query&); friend Query operator&(const Query&, const Query&); friend Query operator|(const Query&, const Query&);public: /*******构造函数,接受一个string,返回一个wordquery的指针*************/ Query(const string& s);//创建一个新的Wordquery类,用来存储查找的单词 /**********覆盖eval的两种形式**************************/ QueryResult eval(const Textquery& t)const { return q->eval(t); }; QueryResult eval(const Textquery& t, size_t min, size_t max){ return q->eval(t, min, max); } /***************输出查询的单词*********************************/ virtual string rep()const { return q->rep(); }; /*************历史查询系统,返回前面第n次的查询结果**************************/ /************************添加记录****************************************************/ void add_history()const{ shared_ptr<Query> p = make_shared<Query>(*this); q->history.push_back(p); }private: /**************私有构造函数,接受指向其他Query_base的智能指针,用于运算符&|~*************/ Query(shared_ptr<Query_base> p) :q(p){} shared_ptr<Query_base> q; //指向各个继承类};/*********************历史查询************/Query& history_query(size_t n){ size_t len = Query_base::history.size(); if (!(Query_base::history.empty()) && n>0 && n <= len)//history不为空&&n是有效的 return *(Query_base::history[len - n]); else throw::out_of_range("invaild n or empty history");}/*******************Wordquery类**************************/class Wordquery :public Query_base{ friend class Query; /*************该构造函数自动调用Query_Base(),虽然没有可初始化的******************************/ Wordquery(const string& s) :query_word(s){} /*************重新定义查询方式eval和查询的文本rep()*********************************/ QueryResult eval(const Textquery& t)const override{return t.query(query_word); }; /***************eval2直接继承************************************/ string rep()const override{ return query_word; }; string query_word;//查找的单词};/********定义Query构造函数函数********************/Query::Query(const string& s) : q(make_shared<Wordquery>(Wordquery(s))){}/********定义Notquery*********************************************/class Notquery : public Query_base{ friend Query operator~(const Query&); /*********构造函数********************/ Notquery(const Query&q) :query(q){} /*************重新定义查询方式eval和查询的文本rep()*********************************/ QueryResult eval(const Textquery& t)const override; string rep()const override { return "~("+ query.rep() + ")"; }; Query query;// q指向某个派生类};/****************重载operator~**********************/Query operator~(const Query&q){return shared_ptr<Query_base>(new Notquery(q));}QueryResult Notquery::eval(const Textquery& t)const{ auto result = query.eval(t);//通过Query运算对象进行虚调用 auto ret_lines = make_shared<set<size_t>>(); auto beg = result.begin(), end = result.end(); for (size_t n = 1; n != result.get_file()->size()+1; ++n)//遍历所有行号 { if (beg == end || (*beg) != n)//n不在result里 ret_lines->insert(n); else if (beg != end)// *beg == n ++beg; } return QueryResult(rep(), result.get_file(), ret_lines);}/*****************定义BinaryQuery:抽象基类****************************/class BinaryQuery : public Query_base{protected: BinaryQuery(const Query& lhs, const Query& rhs, string s) : query1(lhs), query2(rhs), opsym(s){} string opsym;//运算符号 Query query1, query2;//保存该对象构成的状态 /*************覆盖继承而来的虚函数***************************/ string rep()const override { return "( "+ query1.rep() +" "+ opsym+query2.rep()+" "+" )"; }; /**************不定义eval,因此它还是一个纯虚函数******************************/};/*************定义Addquery*********************/class Addquery :public BinaryQuery{ friend Query operator&(const Query&, const Query&); /****************利用抽象基类的构造函数初始化类的对象**************************/ Addquery(const Query& lhs, const Query& rhs) :BinaryQuery(lhs, rhs, "&"){} /****************覆盖相应的纯虚函数************************/ QueryResult eval(const Textquery&)const override;};/*************重载符号函数&************/Query operator&(const Query& lhs, const Query& rhs){ return shared_ptr<Query_base>(new Addquery(lhs, rhs));}QueryResult Addquery::eval(const Textquery& t)const{ auto lhs_result = query1.eval(t), rhs_result = query2.eval(t); auto ret_lines = make_shared<set<size_t>>(); set_intersection(lhs_result.begin(), lhs_result.end(), rhs_result.begin(), rhs_result.end(), inserter(*ret_lines,ret_lines->begin())); return QueryResult(rep(), lhs_result.get_file(), ret_lines);}/*************定义Orquery*********************/class Orquery :public BinaryQuery{ friend Query operator|(const Query&, const Query&); /****************利用抽象基类的构造函数初始化类的对象**************************/ Orquery(const Query& lhs, const Query& rhs) :BinaryQuery(lhs, rhs, "|"){} /****************覆盖相应的纯虚函数************************/ QueryResult eval(const Textquery&)const override;};/*************重载符号函数|************/Query operator|(const Query& lhs, const Query& rhs){ return shared_ptr<Query_base>(new Orquery(lhs, rhs));}QueryResult Orquery::eval(const Textquery& t)const{ auto lhs_result = query1.eval(t), rhs_result = query2.eval(t); auto ret_lines = make_shared<set<size_t>>(lhs_result.begin(), lhs_result.end()); ret_lines->insert(rhs_result.begin(), rhs_result.end()); return QueryResult(rep(), lhs_result.get_file(), ret_lines);}#endif#include "Query_base_derived.h"#include "iterator"#include "vector"using namespace std;int main(){ Textquery t("Text.txt"); auto q = Query("hair")|Query("bird"); q.add_history(); auto p = ~Query("fiery"); p.add_history(); auto q2 = history_query(2)&history_query(1); print(cout, q2.eval(t,3,8)); return 0;}
0 0
- C++primer学习:面向对象程序设计(5):再探文本查询程序
- C++primer学习:文本查询程序
- C++primer学习:面向对象程序设计(2):抽象基类
- C++primer学习笔记----面向对象程序设计(1)
- C++primer学习笔记----面向对象程序设计(2)
- C++ Primer 学习笔记_73_面向对象编程 -再谈文本查询示范
- C++ Primer 学习笔记_74_面向对象编程 -再谈文本查询示范[续/习题]
- 【C++ Primer】文本查询程序再探
- c++primer要点-面向对象程序设计
- C++primer阅读笔记---------------面向对象程序设计
- c++ primer 5ed 15.9文本查询程序再探
- 文本查询程序--摘自c++primer
- 【足迹C++primer】41、文本查询程序
- 【足迹C++primer】56、文本查询程序
- C++Primer 【笔记】文本查询程序 TextQuery
- c++primer 例子文本程序再探
- 《C++primer(第五版)》学习之路-第十五章:面向对象程序设计
- C++primer学习:面向对象程序设计(3):访问控制与继承
- OpenJudge4079:二叉搜索树
- 华年轻盏,淡写悲伤
- iOS动画效果、绘制图形
- 使用DECODE解决去字段中固定首字的匹配问题
- python 文件内搜索关键词并保存行号
- C++primer学习:面向对象程序设计(5):再探文本查询程序
- 配置Maven基础环境生成eclipse工程以及常用命令
- 0012闰年计算的C++实现
- CocoaPods安装和使用教程
- 二分图最大匹配的König定理及其证明
- Redis学习总结(2)——Java使用Redis
- 账号安全登录猜测
- AndroidTestCase来进行android 单元测试简介
- #define _syscall0(type,name) 详解