代码的实现基本是手敲一遍C++ Primer5 15.9文本查询再探,进一步巩固,继承、抽象基类、虚函数等等知识点。
面向对象程序设计
基于Day14天的文本查询进行扩展:
TextQuery类:该类中有个query查询操作,返回一个结果存在QueryResult中
QueryResult类:保存一个单词的查询结果:单词、行号集合、句子集合
1.Query_base_抽象层,提供抽象接口。
虚函数eval:接受一个TextQuery,返回结果存储在QueryResult对象中,eval函数主要在业务层Query_base中实现,eval函数在不同的派生类中重写,返回不一样的结果。
2.Query类--实现层,提供用户外部接口,用于隐藏整个继承体系。
1.Query类提供一个指向Query_base智能指针p,用该指针绑定到Query_base的派生类身上,用户通过对Query对象的操作,间接地创建并且处理Query_base对象。
2.Query有一个接受一个string参数的构造函数,创建一个新的WordQuery对象,然后将指向Query_base的智能指针绑定到派生类WordQuery身上。
3.对于NotQuery,AndQuery,OrQuery这三个派生类,Query提供一个接受指向Query_base的智能指针shared_ptr的构造函数,用来初始化指向Query_base的智能指针p,这个构造函数是为了支持&、|、~运算符而设定。
4.Query类中重写Query_base中的eval(),rep(),间接调用Query_base的派生类对象的eval()和rep()函数。
3.WordQuery类:Query_base的派生类,用于查找一个给定的单词
4.NotQuery类:Query_base的派生类,查询的结果是Query运算对象没有出现的句子集合
5.BinaryQuery类:Query_base派生出来的另外一个抽象基类,表示双目运算查询
6.AndQuery:BinaryQuery的派生类,两个单词同时出现的行的交集
7.OrQuery:BinaryQuery的派生类,两个单词出现的行的并集
完整代码:分为 TextQuery. h、Query_base.h和main.test文件
TextQuery.h
该代码基本已在Day14的文本查询中完成,这里增加了:
1.防止头文件包含宏指令。---不能少
2.QueryResult中多了三个函数:
1. set<line_no>::iterator begin()---返回行号集合的首尾置迭代器
2.set<line_no>::iterator end()---返回行号集合的末尾迭代器
3.shared_ptr<vector<string>> &get_file()//获取句子容器vector的智能指针
#ifndef __TEXTQUERY_H__
#define __TEXTQUERY_H__ //防止头文件重复包含,必须写
#include <iostream>
#include<fstream>
#include <sstream>
#include <iterator>
#include <stdio.h>
#include <vector>
#include <map>
#include <set>
#include <memory>
#include <string>
using std::istringstream;
using std::set;
using std::pair;
using std::ifstream;
using std::ostream;
using std::string;
using std::vector;
using std::cout;
using std::endl;
using std::cerr;
using std::map;
using std::shared_ptr;
using std::cin;
class QueryResult;
class TextQuery
{
public:
using line_no = vector<string>::size_type;//给vector<string>::size_type起别名
//size_type:是个unsigned类型,其长度与机器匹配,ubuntu下,为unsigned long类型
TextQuery(ifstream &);//构造函数,传入文件名
QueryResult query(const string &)const; //查询,
private:
shared_ptr<vector<string>> file;//输入文件
map<string, shared_ptr<set<line_no>>> wm;//一个智能指针管理一个set
};
class QueryResult
{
friend ostream& print(ostream &,const QueryResult &);//打印输出
public:
using line_no = vector<string>::size_type;//给vector<string>::size_type起别名
set<line_no>::iterator begin()
{
return lines->begin();//返回第一个行号的迭代器
}
set<line_no>::iterator end()
{
return lines->end();//最后一个行号的迭代器
}
shared_ptr<vector<string>> &get_file()
{
return file;//单词所对应句子的智能指针
}
QueryResult(string s, shared_ptr<set<line_no>> p,shared_ptr<vector<string>> f)
:sought(s),lines(p),file(f) //有参构造函数,
{
}
private:
string sought;//用于查询单词
shared_ptr<set<line_no>> lines;//保存,出现的行号
shared_ptr<vector<string>> file;//输入文件
};
void parseText(string &text)//解析句子,大写换小写,去掉句子首尾空格
{
for(int i=0;i<text.size();i++)
{
if(text[i]>='A&#