#include"stdafx.h"
#include<iostream>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<fstream>
#include<sstream>
#include<algorithm>
#include<iterator>
using namespace std;
/*
textquery is constructed;
it performs some actions :
firstly read each line from file and write map ,vector
secondly query word
*/
class textquery{
public :
//这个定义了行号。
typedef std::vector<std::string>::size_type line_no;
//从文件读取,调用 store 和buildmap 函数。
void read_file(std::ifstream & is){ store_file(is); build_map();}
std::set<line_no>run_query(const std::string &) const;
std::string text_line(line_no) const;
line_no size () const{return lines_of_text.size();}
private :
void store_file(std::ifstream&);
void build_map();
std::vector<std::string> lines_of_text;
std::map<std::string ,std::set<line_no> > word_map;
};
void textquery::store_file(ifstream &is)
{
string textline;
while(getline(is,textline))
lines_of_text.push_back (textline);
}
void textquery::build_map ()
{
for(line_no line_num=0;line_num!=lines_of_text.size();++line_num)
{
istringstream line(lines_of_text[line_num]);
string word;
while(line>>word)
{
word_map[word].insert(line_num);
}
}
}
set<textquery::line_no> textquery::run_query(const string &query_word) const
{
map<string ,set<line_no> > ::const_iterator loc =word_map.find (query_word);
if(loc==word_map.end())
return set<line_no>();
else
return loc->second;
}
string textquery::text_line (line_no line)const
{
if(line<lines_of_text.size())
return lines_of_text[line];
return 0;
}
/*
query is constructed; $$$$handler class ;
*/
class querybase{
friend class query; //query can call him ;
protected:
typedef textquery::line_no line_no;
virtual ~querybase(){} //this is a question ;
private:
virtual std::set<line_no> eval (const textquery&) const =0;
virtual std::ostream & display(std::ostream& =std::cout)const=0;
};
class query {
friend query operator ~(const query &);
friend query operator |(const query &,const query &);
friend query operator &(const query &,const query &);
public:
query(const std::string&);
query (const query &c):q(c.q),use(c.use){
++*use;
}
~query(){
decr_use();
}
query & operator=(const query& );
std::set<textquery::line_no> eval(const textquery &t)const{
return q->eval(t);
}
std::ostream &display(std::ostream &os) const{
return q->display(os);
}
private:
query(querybase *query ):q(query),use (new std::size_t(1)){}
querybase *q;
std::size_t *use;
void decr_use(){
if(--*use==0)
{
delete q;
delete use;
}
}
};
inline query& query::operator =(const query &rhs)
{
++*rhs.use;
decr_use();
q=rhs.q;
use=rhs.use;
return *this;
}
inline std::ostream & operator <<(std::ostream &os ,const query &q)
{
return q.display(os);
}
/*
*/
class wordquery :public querybase
{
friend class query ;
private :
wordquery (const std::string &s):query_word(s){}
std::string query_word;
std::set<line_no>eval(const textquery &t)const {
return t.run_query(query_word);
}
std::ostream & display (std::ostream &os) const {
return os<<query_word;
}
};
inline query::query(const std::string& word): q(new wordquery(word)), use(new std::size_t(1)) {}
///
// class NotQuery
class notquery: public querybase
{
friend query operator~ (const query &);
notquery(const query &q): query1(q){}
// concrete class: NotQuery defines all inherited pure virtual functions
std::set<line_no> eval(const textquery&) const;
std::ostream& display(std::ostream &os) const {
return os << "~(" << query1 << ")";
}
const query query1;
};
///
// class BinaryQuery
class binaryquery: public querybase
{
protected:
binaryquery(const query &left, const query &right, const std::string &op):
lhs(left), rhs(right), oper(op) {}
// abstract class: BinaryQuery doesn't define eval
std::ostream& display(std::ostream &os) const {
return os << "(" << lhs << " " << oper << " " << rhs << ")";
}
const query lhs, rhs;
const std::string oper;
};
//
// class AndQuery
class andquery: public binaryquery
{
friend query operator& (const query&, const query&);
andquery(const query &left, const query &right): binaryquery(left, right, "&") {}
// concrete class: AndQuery inherits display and defines remaining pure virtual
std::set<line_no> eval(const textquery&) const;
};
//
// class OrQuery
class orquery: public binaryquery
{
friend query operator| (const query&, const query&);
orquery(const query &left, const query &right): binaryquery(left, right, "|") {}
// concrete class: OrQuery inherits display and defines remaining pure virtual
std::set<line_no> eval(const textquery&) const;
};
inline query operator& (const query &lhs, const query &rhs)
{
return new andquery(lhs, rhs);
}
inline query operator| (const query &lhs, const query &rhs)
{
return new orquery(lhs, rhs);
}
inline query operator~ (const query & q)
{
return new notquery(q);
}
set<textquery::line_no> notquery::eval(const textquery &file) const
{
// virtual call through the Query handle to eval
set<line_no> has_val = query1.eval(file);
set<line_no> ret;
// for each line in the input file, check whether that line is in has_val
for (line_no n = 0; n != file.size(); ++n)
if (has_val.find(n) == has_val.end())
ret.insert(n);
return ret;
}
set<textquery::line_no> andquery::eval(const textquery &file) const
{
// virtual calls through the Query handle to get result sets for operands
set<line_no> left = lhs.eval(file);
set<line_no> right = rhs.eval(file);
set<line_no> ret;
set_intersection(left.begin(), left.end(), right.begin(), right.end(), inserter(ret, ret.begin()));
return ret;
}
set<textquery::line_no> orquery::eval(const textquery &file) const
{
// virtual calls through the Query handle to get result sets for operands
set<line_no> right = rhs.eval(file);
set<line_no> ret = lhs.eval(file);
ret.insert(right.begin(), right.end());
return ret;
}
void print_result(const set<textquery::line_no>& locs, const textquery& file)
{
typedef set<textquery::line_no> line_nums;
line_nums::size_type size = locs.size();
cout<<" occurs "<<size<<(size>1?"Times":"Time")<<endl;
line_nums::const_iterator it = locs.begin();
for(; it!=locs.end(); ++it)
cout<<(*it)+1<<"\t"<<file.text_line(*it)<<endl;
}
int main( int argc,char **argv)
{
ifstream is("c://text.txt");
textquery tq;
tq.read_file(is);
query q = ~query("the");
std::set<textquery::line_no> locs = q.eval(tq);
q.display(cout);
// string s("((fiery & bird) | wind)");
print_result(locs, tq);
return 0;
}
C++ Primer 第15章例子-文本查询程序
最新推荐文章于 2022-06-18 14:57:45 发布