您的位置:首页 > 编程语言 > C语言/C++

C++primer 文本查询练习

2011-05-11 18:13 218 查看
// header file

#pragma once

#include "TextQuery.h"

#include <algorithm>

#include <iterator>

namespace StringQuery{

class QueryBase

{

friend class Query;

protected:

typedef TextQuery::line_no line_no;

virtual ~QueryBase(void){};

private:

virtual std::set<line_no> eval(const TextQuery& t) const = 0;

virtual std::ostream& display(std::ostream& os = std::cout) const = 0;

};

class Query

{

public:

friend Query operator~(const Query& );

friend Query operator|(const Query& ,const Query& );

friend Query operator&(const Query& ,const Query& );

std::set<TextQuery::line_no> eval(const TextQuery& tq) const

{

return q->eval(tq);

}

std::ostream& display(std::ostream& os) const

{

return q->display(os);

}

Query& operator=(const Query &);

public:

Query(const std::string &s);

Query(const Query& query):q(query.q),use(query.use){++*use;}

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

~Query(void){decr_use();}

private:

QueryBase *q;

std::size_t *use;

inline void decr_use(void)

{

if(--*use==0)

{

delete q;

delete use;

}

}

};

inline std::ostream& operator<<(std::ostream& os,const Query &q)

{ return q.display(os); }

inline Query& Query::operator=(const Query &rhs)

{

++*rhs.use;

decr_use();

q = rhs.q;

use = rhs.use;

return *this;

}

class WordQuery:public QueryBase

{

friend class Query;

WordQuery(const std::string &s):query_word(s) { }

std::set<line_no> eval(const TextQuery &t) const

{ return t.run_query(query_word); }

std::ostream& display(std::ostream &os = std::cout) const

{ return os << query_word; }

std::string query_word;

};

inline

Query::Query(const std::string &s):q(new WordQuery(s)),

use(new std::size_t(1)) { }

class NotQuery:public QueryBase

{

friend Query operator~(const Query& query);

NotQuery(const Query& q):query(q) { }

std::set<line_no> eval(const TextQuery& file) const;

std::ostream& display(std::ostream& os = std::cout) const

{ return os << "~(" << query << ")"; }

const Query query;//implemente binding

};

class BinaryQuery:public QueryBase

{

protected:

BinaryQuery(const Query &rl,const Query &rr,const std::string &op):rhl(rl),rhr(rr),oper(op){}

std::ostream& display(std::ostream &os) const

{ return os << "~(" << rhl << "" << oper << " " << rhr << ")"; }

const Query rhl,rhr;

const std::string oper;

};

class OrQuery:public BinaryQuery

{

friend Query operator|(const Query &,const Query &);

OrQuery(const Query& rl,const Query& rr):BinaryQuery(rl,rr,"|"){}

std::set<line_no> eval(const TextQuery &file) const;

};

class AndQuery:public BinaryQuery

{

friend Query operator&(const Query &,const Query &);

AndQuery(const Query &rl,const Query &rr):BinaryQuery(rl,rr,"&"){}

std::set<line_no> eval(const TextQuery &file) const;

};

inline Query operator~(const Query& query)

{ return new NotQuery(query); }

inline Query operator|(const Query& query_left,const Query& query_right)

{ return new OrQuery(query_left,query_right); }

inline Query operator&(const Query& query_left,const Query& query_right)

{ return new AndQuery(query_left,query_right); }

Query parse_expression(const std::string &QueryString);

}

// cpp file

#include "Query.h"

#include "TextQuery.h"

#include <set>

#include <algorithm>

#include <iostream>

using std::set;

using std::vector;

using std::string;

using std::ostream;

using std::inserter;

using std::set_difference;

using std::set_union;

using std::set_intersection;

namespace StringQuery{

set<TextQuery::line_no> NotQuery::eval(const TextQuery &file) const

{

set<line_no> has_val = query.eval(file);

set<line_no> not_val;

for(line_no lineSum = 0;lineSum < file.size();++lineSum)

{

if( has_val.find(lineSum)==has_val.end() )

not_val.insert(lineSum);

}

return not_val;

}

set<TextQuery::line_no> OrQuery::eval(const TextQuery &file) const

{

set<line_no> right = rhr.eval(file),

ret_lines = rhl.eval(file);

ret_lines.insert( right.begin(),right.end() );

return ret_lines;

}

set<TextQuery::line_no> AndQuery::eval(const TextQuery &file) const

{

set<line_no> rval = rhr.eval(file),

lval = rhl.eval(file);

set<line_no> retlines;

set_intersection( rval.begin(),rval.end(),lval.begin(),lval.end(),inserter(retlines,retlines.begin()) );

return retlines;

}

bool inputValidate(const std::string &QueryString)

{

std::string::size_type pos = QueryString.find("~|&");

if(std::string::npos != pos)

if( std::string::npos != QueryString.find("~|&",++pos) )

return false;

return true;

}

Query parse_expression(const std::string &QueryString)

{

vector<string> words;

vector<string> opers;

string::size_type pos_pre = 0;

string::size_type pos_cur = QueryString.find_first_of("~|&");

while(string::npos != pos_cur)

{

string word = QueryString.substr( pos_pre,pos_cur - pos_pre );

words.push_back(word);

string oper = QueryString.substr(pos_cur,1);

opers.push_back(oper);

pos_pre = pos_cur+1;

pos_cur = QueryString.find_first_of("~|&",pos_pre);

}

string word = QueryString.substr(pos_pre,QueryString.size()-pos_pre);

words.push_back(word);

vector<string>::const_reverse_iterator words_it = words.rbegin();

vector<string>::const_reverse_iterator opers_it = opers.rbegin();

Query query(*words_it);

words_it++;

for(;words_it != words.rend();words_it++)

{

if( opers_it != opers.rend() )

{

switch((*opers_it).at(0))

{

case '~':

query = ~query;

break;

case '|':

query = query|Query(*words_it);

words_it++;

break;

case '&':

query = query&Query(*words_it);

words_it++;

break;

default:

std::cerr << "It's an operator from Mars!";

}

opers_it++;

}

}

//Query query( *(new string("temp")) );

return query;

}

}

// Finder.cpp : Defines the entry point for the console application.

//

#include "stdafx.h"

#include <conio.h>

#include "TextQuery.h"

#include "Query.h"

//#include <boost/regex.hpp>

//using namespace boost;

using std::string;

using std::set;

using std::cin;

using std::cout;

using std::endl;

void printResult(const string& word,const char* filename);

int _tmain(int argc, _TCHAR* argv[])

{

if(3 > argc)

{

cout << "Usage:program <Filename> <QueryWord> ." << endl;

}

else

{

string word;

for(int count = 2;count < argc;count++)

{

word += argv[count];

}

StringQuery::Query q( StringQuery::parse_expression(word) );

TextQuery tq;

tq.readFile(argv[1]);

q.display(std::cout);

set<TextQuery::line_no> rec = q.eval(tq);

set<TextQuery::line_no>::iterator it = rec.begin();

for(;it != rec.end();++it)

{

cout << " ( line " << *it << " ) " << tq.textLine(*it) << endl;

}

}

_getch();

return 0;

}

void printResult(const string& word,const char* filename)

{

TextQuery tq;

tq.readFile(filename);

set<TextQuery::line_no> res = tq.run_query(word);

cout << "Found " << res.size() << " items." << endl;

set<TextQuery::line_no>::iterator it = res.begin();

for(;it != res.end();++it)

{

cout << " ( line " << *it << " ) " << tq.textLine(*it) << endl;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐