现在的位置: 首页 > 综合 > 正文

文本查询小例子—涉及多态 句柄类

2018年02月19日 ⁄ 综合 ⁄ 共 6169字 ⁄ 字号 评论关闭

最近实现了c++prime上的文本查询的小例子,见第四版15章最后一节。涉及到了多态,句柄类,故在此给出实现的源代码,以便后续查看。

一:系统要求:

图片无法上传---待传

二:代码

(1)queryWord.h ------------queryWorld是真正用来实现保存的数据结构及查询操作的。

#ifndef QUERYWORD
#define QUERYWORD
#include <map>
#include <set>
#include <vector>
#include <string>
#include <fstream>
using namespace std;
class QueryWord{
public:
	typedef vector<string>::size_type line_no;
	void readFiles(ifstream &);           // 将文本文件的内容读取到数据结构中
	set<line_no> run_query(const string&)const ;    //  针对给定的string来查询结果
	void print(set<line_no> &, const string &str)const;   // 将结果进行输出
	line_no size()const{return content.size();}            
private:
	string getLine(line_no) const;
	vector<string> content;              // 用来保存读取的文本 每个string对应一行 因此下标就可以看做是行号了
	map<string, set<line_no> > textMap;    // map 用来保存单词及该单词出现的行
};

#endif

queryWorld.cpp

#include <iostream>
#include "queryWord.h"
#include <sstream>
#include "query.h"
using namespace std;

void QueryWord::readFiles(ifstream &infile){
	if(!infile){
		cout << "fail to load file" << endl;
		return;
	}
	string str;
	line_no line = 0;
	while(getline(infile, str)){
		content.push_back(str);
		
		//  采用istringstream来读取每个单词
		istringstream is(str);
		string word;
		while(is >> word){
			for(string::iterator iter = word.begin(); iter != word.end();){
				if(!isalnum(*iter))iter = word.erase(iter);
				else iter++;
			}
			textMap[word].insert(line);
		}
		line++;
	}
}

//  针对每个单词,返回该单词所对应的set集合 即为查询的单词所对应的行号
set<QueryWord::line_no> QueryWord::run_query(const string &query_word)const{
	map<string, set<line_no> >::const_iterator iter = textMap.find(query_word);
	if(iter == textMap.end()) return set<line_no>();
	else return iter->second;

}

//  返回所对应行号所对应的内容
string QueryWord::getLine(line_no line) const{
	return content[line];
}

void QueryWord::print(set<line_no> &result, const string &str)const{
	cout << str << " match occurs " << result.size() << " times:" << endl;
	for(set<QueryWord::line_no>::iterator iter = result.begin(); iter != result.end(); iter++){
		cout << "(line " << (*iter)+1 << ") " << getLine(*iter) << endl; 
	}
	cout << endl;
	cout << "Executed Query for: ";
}

(2)queryBase.h:查询的是基类,为抽象类  通过虚函数eval来实现得到查询的结果 

// 查询的是基类,为抽象类  通过虚函数eval来实现得到查询的结果 
//定义了句柄类Query,用来存储和管理基类指针 
// 
#ifndef QUERYBASE
#define QUERYBASE
#include "queryWord.h"
#include <iostream>
using namespace std;
class QueryBase{
	friend class Query;	
protected:
	typedef QueryWord::line_no line_no;
	virtual ~QueryBase(){}          //  有虚函数要用虚析构函数 
private:
	
	virtual set<line_no> eval(QueryWord &query_word)=0;
};

#endif

(3)query.h -------------句柄类,所有的操作都归并到操作句柄类,用来存储和管理基类指针 

#ifndef QUERY
#define QUERY
#include "queryBase.h"
#include <string>
using namespace std;
#include "wordQuery.h"

class Query{
public:
	friend Query operator&(Query&, Query&);
	friend Query operator|(Query&, Query&);
	friend Query operator~(Query&);

	Query():qb(NULL), p(new size_t(1)){}    // 必须 有不然notWordQuery中成员变量无法定义
	Query(string&);             //  得到一个wordQuery
	Query(const Query &q):qb(q.qb), p(q.p){++*p;};   // 复制构造函数
	Query operator=(Query &q);          // 赋值操作符
	set<QueryWord::line_no> eval(QueryWord &query_word){ return qb->eval(query_word);}   //  利用的是多态 实质上调用的是各派生类的eval函数
	~Query(){deQuery();}
private:
	void deQuery(){if(--*p == 0){delete qb, delete p;}}
	Query(QueryBase*);
	QueryBase *qb;        // 基类指针
	size_t *p;        // 计数指针
};


#endif

query.cpp

#include "query.h"

Query Query::operator=(Query &q){
	++*q.p;
	deQuery();
	qb = q.qb;
	p = q.p;
	return *this;
}
Query::Query(string &word){
	qb = new WordQuery(word);
	p = new size_t(1);
}

Query::Query(QueryBase*q):qb(q), p(new size_t(1)){};

(4)派生类 --- 与或非及普通单词查询

wordQuery.h

#ifndef WORDQUERY
#define WORDQUERY
#include "queryBase.h"
#include "queryWord.h"
#include <iostream>
using namespace std;
class WordQuery:public QueryBase{
	friend class Query;
	WordQuery(string &word):queryWord(word){};
	set<line_no> eval(QueryWord &query_word){return query_word.run_query(queryWord);}   //
	string queryWord;
	~WordQuery(){}
};

#endif

notWordQuery.h   -----非

#ifndef NOTWORDQUERY
#define NOTWORDQUERY
#include "query.h"
#include <iostream>
using namespace std;
class NotWordQuery:public QueryBase{
	friend Query operator~(Query &);
	NotWordQuery(Query &query):q(query){}
	set<line_no> eval(QueryWord &query_word);
	Query q;
	~NotWordQuery(){};
};

#endif

orWordQuery.h ----------或

#ifndef ORWORDQUERY
#define ORWORDQUERY
#include "binaryQuery.h"
class OrWordQuery:public BinaryQuery{
	friend Query operator|(Query &, Query &);
	set<line_no> eval(QueryWord &query_word);
	OrWordQuery(Query &l, Query &r):BinaryQuery(l, r, string("|")){}
};
#endif

AndWordQuery.h -----------与

#ifndef ANDWORDQUERY
#define ANDWORDQUERY
#include "binaryQuery.h"
class AndWordQuery:public BinaryQuery{
	friend Query operator&(Query &, Query &);
	set<line_no> eval(QueryWord &query_word);
	AndWordQuery(Query &l, Query &r):BinaryQuery(l, r, string("&")){}
};
#endif

wordQuery.cpp ----- 各派生类eval的实现

#include "notWordQuery.h"
#include "queryWord.h"
#include "andWordQuery.h"
#include "orWordQuery.h"
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;

//  非操作符所对应的查询eval操作
set<QueryWord::line_no> NotWordQuery::eval(QueryWord &query_word){   
	set<line_no> result = q.eval(query_word);
	set<line_no> ret_result;
	for(line_no i = 0; i < query_word.size(); i++)
	{
		set<line_no>::iterator iter = result.find(i);
		if(iter == result.end()) ret_result.insert(i);
	}
	return  ret_result;
}

//  与操作符所对应的查询eval操作
set<QueryWord::line_no> OrWordQuery::eval(QueryWord &query_word){
	set<line_no> l = lhs.eval(query_word);
	set<line_no> r = rhs.eval(query_word);
	set<line_no> ret_result(l.begin(), l.end());
	ret_result.insert(r.begin(), r.end());
	return ret_result;
}

//  与操作符所对应的查询eval操作,使用了set_intersection来实现与操作
set<QueryWord::line_no> AndWordQuery::eval(QueryWord &query_word){
	set<line_no> l = lhs.eval(query_word);
	set<line_no> r = rhs.eval(query_word);
	set<line_no> ret_result;
	set_intersection(l.begin(), l.end(),r.begin(), r.end(), inserter(ret_result, ret_result.begin()));
	return ret_result;
}

(5)主函数Main.cpp

#include <iostream>
#include "queryWord.h"
#include "query.h"
#include <fstream>
#include "notWordQuery.h"
#include "andWordQuery.h"
#include "orWordQuery.h"
#include <string>
using namespace std;


//   实质上调用了Query(QueryBase*)这个构造函数
inline Query operator&(Query& l,  Query& r){
	return new AndWordQuery(l, r);
}
inline Query operator|(Query&l, Query&r){
	return new OrWordQuery(l, r);
}
inline Query operator~(Query &q){
	return new NotWordQuery(q);
}

int main(){
	QueryWord qw;
	ifstream infile("F:\\11.txt");
	qw.readFiles(infile);
	string str;
	cout << "Executed Query for: ";

	/*while(cin >> str){
		Query q1(str);
		set<QueryWord::line_no> result = q1.eval(qw);
		qw.print(result, str);
	}*/
	cin >> str;
	Query q1(str);
	set<QueryWord::line_no> result1 = q1.eval(qw);
	qw.print(result1, str);
	
	cout << "~" << endl;
	Query q2 = ~q1;
	set<QueryWord::line_no> result2 = q2.eval(qw);
	qw.print(result2, str);

	cout << "&" << endl;

	Query q4 = q1 & q2;
	set<QueryWord::line_no> result3 = q4.eval(qw);
	qw.print(result3, str);
	return 0;
}

三:运行结果

待上传....

抱歉!评论已关闭.