当前位置: 首页 > news >正文

c++ 派生类 文本查询程序再探

Query_base类和Query类

//这是一个抽象基类,具体的查询类型从中派生,所有成员都是private的
class Query_base {friend class Query;protected:using line_no = TextQuery::line_no;//用于level函数virtual ~Query_base() = default;private://eval返回与当前Query匹配的QueryResultvirtual QueryResult eval(const TextQuery&) const = 0;//rep是表示查询 的一个stringvirtual std::string rep() const = 0;
};//这是一个管理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{return q->eval(t);}std::string rep() const {return q->req();}private:Query(std::shared_ptr<Query_base> query):q(query){  }std::shared_ptr<Query_base> q;
};

Query的输出运算符

std::ostream & 
operator<<(std::ostream &os,const Query &query)
{//Query::rep通过它的Query_base指针对rep()进行虚调用return os<<query.rep();
}Query andq = Query(sought1) & Query(sought2);
cout<<andq<<endl;

派生类

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

NotQuery类及 ~运算符

class NotQuery : public Query_base {friend Query operator~(const Query &);NotQuery(const Query &q):query(q){ }//具体的类:NotQuery将定义所有继承而来的纯虚函数std::string rep() const {return "~(" + query.rep() + ")";}QueryResult eval(const TextQuery&) const;Query query;
};
inline Query operator~(const Query &operand)
{return std::shared_ptr<Query_base>(new NotQuery(oprand));
}//分配一个新的NotQuery对象
//将所得的NotQuery指针绑定到一个shared_ptr<Query_base>
shared_ptr<Query_base> tmp(new NotQuery(expr));
return Query(tmp);  //使用接受一个shared_ptr的Query构造函数

BinaryQuery类

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

AndQuery类、OrQuery类及相应的运算符

    class AndQuery : public BinaryQuery {friend Query operator&(const Query&,const Query&);AndQuery(const Query &left,const Query &right) : BinaryQuery(left,right,"&"){ }//具体的类: AndQuery继承了rep并且定义了其他纯虚函数QueryResult eval(const TextQuery&) const;};inline Query operator&(const Query &lhs,const Query &rhs){return std::shared_ptr<Query_base>(new AndQuery(lhs,rhs));}class OrQuery : public BinaryQuery{friend Query operator|(const Query&,const Query&);OrQuery(const Query &left,const Query &right):BinaryQuery(left,right,"|"){ }QueryResult eval(const TextQuery&)const;};inline Query operator|(const Query &lhs,const Query &rhs){return std::shared_ptr<Query_base>(new OrQuery(lhs,rhs));}

eval函数

//返回运算对象查询结果set的并集
OrQuery::eval(const TextQuery& text) const
{//通过Query成员lhs和rhs进行的虚调用//调用eval返回每个运算对象的QueryResultauto right = rhs.eval(text),left = lhs.eval(text);//将左侧运算对象的行号拷贝到结果set中auto ret_lines =make_shared<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());
}//返回运算对象查询结果set的交集
QueryResult
AndQuery::eval(const TextQuery& text) const
{//通过Query运算对象进行的虚调用,以获得运算对象的查询结果setauto left = lhs.eval(text),right = rhs.eval(text);//保存left 和 right交集的setauto ret_lines =  make_shared<set<line_no>>();//将两个范围的交集写入一个目的迭代器中//本次调用的目的迭代器向ret添加元素set_intersection(left.begin(),left.end(),right.begin(),right.end(),inserter(*ret_lines,ret_lines->begin()));return QueryResult(rep(),ret_lines,left.get_file());
}//返回运算对象的结果set中不存在的行
QueryResult
NotQuery::eval(const TextQuery& text) const
{//通过Query运算对象对eval进行虚调用auto result = query.eval(text);//开始时结果set为空auto ret_lines = make_shared<set<line_no>>();//我们必须在运算对象出现的所有行中进行迭代auto beg = result.begin(),end = result.end();//对于输入文件的每一行,如果该行不在result当中,则将其添加到ret_linesauto sz = result.get_file()->size();for(size_t n = 0;n != sz; ++n){//如果我们还没有处理完result的所有行//检查当前行是否存在if(beg = end || *beg != n)ret_lines->insert(n);   //如果不在result当中,添加这一行else if(beg != end)++beg;  //否则继续获取result的下一行(如果有的话)}return QueryResult(rep(),ret_lines,result.get_file());
}
http://www.lryc.cn/news/96125.html

相关文章:

  • 17. 电话号码的字母组合
  • Redis 基础知识和核心概念解析:理解 Redis 的键值操作和过期策略
  • Jenkins中sh函数的用法
  • Android 之 Canvas API 详解 (Part 3) Matrix 和 drawBitmapMesh
  • 基于Ubuntu 22.04 编译chip-tool工具
  • opencv-17 脸部打码及解码
  • JVM分享
  • Apache Dubbo CVE-2021-36162 挖掘过程
  • 开源框架面试题目整理
  • Mr. Cappuccino的第52杯咖啡——Mybatis环境搭建与使用
  • 了解Unity编辑器之组件篇Tilemap(五)
  • Linux字符设备操作函数
  • 吉林大学计算机软件考研经验贴
  • 2023-07-26力扣每日一题-区间翻转线段树
  • Java设计模式之 -- 桥接模式
  • 【node.js】02-path模块
  • 攻防世界-Reverse-re1
  • AES加密的基本常识和封装类
  • elasticsearch使用记录
  • UNI-APP_横屏切换竖屏出现样式混乱问题
  • 数据可视化(3)
  • AI面试官:MD5、DES、RSA、AES加密
  • Shell脚本学习-$$特殊变量
  • vscode中python插件过新导致无法正常debug问题解决安装vscode以前版本python插件教程
  • chrome macos编译
  • Linux环境下Elasticsearch相关软件安装
  • 【趟坑记录】d3.zoom()的正确使用姿势 @d3.v7
  • 基于 Docker + Nginx + Gitlab-runner 实现前端自动化部署流程
  • make/makefile的使用
  • Flutter中Navigator 跳转传参数和反向传参数