IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发工具 -> C++Primer第十五章Query的实现 -> 正文阅读

[开发工具]C++Primer第十五章Query的实现

笔记

重点在于理解Query_base的继承体系,派生类有WordQueryNotQueryAndQueryOrQuery。并且创建一个Query类来作为Query_base的接口类,通过Query类对外界隐藏Query_base继承体系,更加方便的管理Query_base派生类直接的转换

C++Prime习题集解答

书中的实现方式是用Query类封装了Query_base指针,管理实际查询处理用到的不同Query类型对象.如果不使用Query类,则设计使用Query的地方,都要改为Query_base指针。如创建单个词查询,就必须创建WordQuery类而不是Query类,几个重载的布尔运算符也不能针对Query,而需针对Query_base指针,将结果赋予Query_base指针,然后再进行下一步操作,资源管理方面也需要重新设计,因此当前设计仍是最佳方式

类图:

类图
代码(建议自己敲一遍)

#pragma once
#ifndef QUERY_H
#define QUERY_H
#include<memory>
#include<vector>
#include<string>
#include<map>
#include<set>
#include<istream>
#include<fstream>
#include<iostream>
#include<algorithm>
#include<sstream>
using std::shared_ptr;
using std::vector;
using std::string;
using std::map;
using std::set;
using std::ifstream;
using std::ostream;
using std::cout;
using std::endl;
using std::istringstream;
using std::make_shared;
//查询结果类
class QueryResult {
public:
	typedef vector<string>::size_type line_no;
	friend ostream& print(ostream&, const QueryResult&);
	friend ostream& operator<<(ostream&, const QueryResult&);
	QueryResult(const string& w,shared_ptr<set<line_no>> n,shared_ptr<vector<string>> i):word(w),nos(n),input(i){}
	//返回指向保存行号的set的迭代器
	set<line_no>::iterator begin()const{
		return nos->begin();
	}
	set<line_no>::iterator end()const {
		return nos->end();
	}
	shared_ptr<vector<string>> get_file()const{
		return input;
	}
private:
	string word;//查询单词
	shared_ptr<set<line_no>> nos;//单词对应的行数
	shared_ptr<vector<string>> input;//输入文件的vector指针
};
//文本查询类
class TextQuery{
public:
	typedef vector<string>::size_type line_no;
	//构造函数
	TextQuery(ifstream&);
	//查询函数
	QueryResult query(const string&)const;
private:
	shared_ptr<vector<string>> input;//输入文件
	map<string, shared_ptr<set<line_no>>> result;//单词对应的行号
};

ostream& print(ostream& os, const QueryResult& qr) {
	os << qr.word << " occurs: " << qr.nos->size() << (qr.nos->size() > 1 ? "times" : "time" )<< endl;
	for (int i : *qr.nos) {
		cout << "\t(line " << i + 1 << ") " << qr.input->at(i) << endl;
	}
	return os;
}

TextQuery::TextQuery(ifstream& ifs) :input(new vector<string>) {
	line_no lineNo = 0;	
	for (string line; getline(ifs, line); lineNo++) {
		input->push_back(line);
		istringstream line_stream(line);
		string text, word;
		for (; line_stream >> text; word.clear()) {
			remove_copy_if(text.begin(), text.end(), std::back_inserter(word), ispunct);
			auto& nos = result[word];
			if (!nos)nos.reset(new set<line_no>);//对象是智能指针
			nos->insert(lineNo);//对象是set
		}
	}
}
QueryResult TextQuery::query(const string& word) const {
	static shared_ptr<set<line_no>> nos(new set<line_no>);
	auto found = result.find(word);
	if (found==result.end()) {
		return QueryResult(word, nos, input);
	}
	else {
		return QueryResult(word, found->second,input);
	}
}


//查询基类
class Query_base {
	friend class Query;
protected:
	using line_no = TextQuery::line_no;
	virtual ~Query_base() = default;
private:
	virtual QueryResult eval(const TextQuery&)const = 0;
	virtual string rep()const = 0;
};

//查询接口类
class Query {
	//友元操作符
	friend Query operator&(const Query&,const Query&);
	friend Query operator~(const Query&);
	friend Query operator|(const Query&, const Query&);
public:
	Query(const string& word);//只向外界提供wordQuery成员的初始化

	string rep()const{
		return q->rep();
	}
	//查询函数接口
	QueryResult eval(const TextQuery& tq)const {
		return q->eval(tq);
	}
private:
	//此构造函数不允许外界调用
	Query(shared_ptr<Query_base> query) :q(query) { cout << "调用 Query ctor" << endl; };
	//指向查询类的指针
	shared_ptr<Query_base> q;
};
//重载<<输出Query
ostream& operator<<(ostream& os,const Query& query) {
	return os << query.rep() << endl;
}
//重载<<输出QueryResult
ostream& operator<<(ostream& os, const QueryResult& qr) {
	os << qr.word << " occurs: " << qr.nos->size() << (qr.nos->size() > 1 ? "times" : "time") << endl;
	for (int i : *qr.nos) {
		cout << "\t(line " << i + 1 << ") " << qr.input->at(i) << endl;
	}
	return os;
}
//单词查询类
class WordQuery :public Query_base {
	friend class Query;

	WordQuery(const string& s) :query_word(s) { cout << "调用 wordQuery ctor" << endl; }

	string rep() const override{
		return query_word;
	}

	QueryResult eval(const TextQuery& tq)const override {
		return tq.query(query_word);
	}

	string query_word;
};

//Query构造函数
inline
Query::Query(const string& word) :q(new WordQuery(word)) { cout << "调用 Query ctor" << endl; };

//Not查询类
class NotQuery : public Query_base {
	friend Query operator~(const Query&);
	
	NotQuery(const Query &q) :query(q){ cout << "调用 NotQuery ctor" << endl; }

	string rep()const override{
		return "~("+query.rep()+")";
	}

	QueryResult eval(const TextQuery&tq)const override {
		auto result = query.eval(tq);

		auto ret_lines = make_shared<set<line_no>>();
		auto beg = result.begin(), end = result.end();
		line_no 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 query;
};

inline 
Query operator~(const Query& query) {
	return shared_ptr<Query_base>(new NotQuery(query));
}

//二元查询抽象基类
class BinaryQuery :public Query_base {
protected:
	BinaryQuery(const Query&l,const Query&r,const string& op):lhs(l),rhs(r),opSym(op){ cout << "调用 BinaryQuery ctor" << endl; }
	string rep()const override{
		return lhs.rep() + opSym + rhs.rep();
	}
	Query lhs, rhs;
	string opSym;
};

//and查询类
class AndQuery :public BinaryQuery {
	friend Query operator&(const Query&, const Query&);

	AndQuery(const Query& l, const Query& r) :BinaryQuery(l, r, "&") { cout << "调用 AndQuery ctor" << endl; };
	QueryResult eval(const TextQuery& tq)const override {
		auto left = lhs.eval(tq), right = rhs.eval(tq);
		auto ret_line = make_shared<set<line_no>>();//构造一个智能指针,指向空的结果集合

		set_intersection(left.begin(), left.end(), right.begin(), right.end(), inserter(*ret_line, ret_line->begin()));//取并集
		//inserter(*ret_line,ret_line->begin())插入迭代器,调用的是set<line_no>::insert();

		return QueryResult(rep(), ret_line, left.get_file());
	}

};
inline
Query operator&(const Query& lhs, const Query& rhs) {
	return shared_ptr<Query_base>(new AndQuery(lhs,rhs));
}

//Or查询类
class OrQuery:public BinaryQuery {
	friend Query operator|(const Query&, const Query&);

	OrQuery(const Query& l, const Query& r) :BinaryQuery(l, r, "|") { cout << "调用 OrQuery ctor" << endl; };
	//Or类型版本的eval函数
	QueryResult eval(const TextQuery& tq)const override {
		auto left = lhs.eval(tq), right = rhs.eval(tq);//分别获取左右两部分的查询结果
		auto ret_line = make_shared<set<line_no>>(left.begin(), left.end());
		ret_line->insert(right.begin(), right.end());//取左右两部分的查询并集

		return QueryResult(rep(),ret_line,left.get_file());//返回查询结果
	}
};
inline 
Query operator|(const Query& lhs, const Query& rhs) {
	return shared_ptr<Query_base>(new OrQuery(lhs, rhs));
}


#endif

主函数

#include"Query.h"
#include<iostream>
using std::cout;
using std::cin;
string fileName = "./testFile/test15.9.4.txt";//文件路径

void runQuery(ifstream& ifs,Query& q) {
	TextQuery tq(ifs);
	cout << q;//打印处理对象,重载了操作符
	cout << q.eval(tq);//打印处理结果,重载了操作符
}

int main(int argc, char** argv) {
	ifstream ifs(fileName);
	Query q = Query("fiery") & Query("bird") | Query("wind");
	if (ifs)
		runQuery(ifs,q);
	else
		std::cerr << "Cannot open this file!" << fileName;
	
}

教材所提供的查询文段

Alice Emma has long flowing red hair.
Her Daddy says when the wind blows
through her hair, it looks almost alive,
like a fiery bird in flight.
A beautiful fiery bird, he tells her,
magical but untamed.
"Daddy, shush, there is no such thing,"
she tells him, at the same time wanting
him to tell her more.
Shyly, she saks, "I mean,Daddy, is there?"
  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2021-11-23 12:34:27  更:2021-11-23 12:35:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/24 2:42:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计