最近实现了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;
}
三:运行结果
待上传....