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

C++ Primer 学习笔记_74_面向对象编程 -再谈文本查询示范[续/习题]

2016-05-09 18:53 447 查看


面向对象编程


--再谈文本查询示例[续/习题]

//P522 习题15.41
//1 in TextQuery.h
#ifndef TEXTQUERY_H_INCLUDED
#define TEXTQUERY_H_INCLUDED

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <stdexcept>

using namespace std;

class TextQuery
{
public:
typedef std::vector<std::string>::size_type line_no;
typedef string::size_type str_size;

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;

private:
void store_file(std::ifstream &);
void build_map();

std::vector<std::string> line_of_text;
std::map< std::string,std::set<line_no> > word_map;
};

#endif // TEXTQUERY_H_INCLUDED

//2 in TextQuery.cpp
#include "TextQuery.h"

void TextQuery::store_file(ifstream &is)
{
string textline;
while (getline(is,textline))
{
line_of_text.push_back(textline);
}
}

void TextQuery::build_map()
{
for (line_no line_num = 0;
line_num != line_of_text.size();
++line_num)
{
istringstream line(line_of_text[line_num]);
string word;

while (line >> word)
{
word_map[word].insert(line_num);
}
}
}

set<TextQuery::line_no>
TextQuery::run_query(const std::string &query_word) const
{
map<string,set<line_no> >::const_iterator loc =
word_map.find(query_word);

if (loc == word_map.end())
{
return set<TextQuery::line_no>();
}
else
{
return loc -> second;
}
}

string TextQuery::text_line(line_no line) const
{
if (line < line_of_text.size())
{
return line_of_text[line];
}
throw out_of_range("line number out of range");
}

TextQuery::str_size TextQuery::size() const
{
return line_of_text.size();
}

//3 in Query.h
#ifndef QUERY_H_INCLUDED
#define QUERY_H_INCLUDED

#include "TextQuery.h"
#include <iostream>
#include <fstream>
#include <string>
#include <set>
#include <algorithm>

using namespace std;

class Query_base
{
friend class Query;

protected:
typedef TextQuery::line_no line_no;
virtual ~Query_base() {}

private:
virtual set<line_no> eval(const TextQuery &) const = 0;
virtual ostream &display(ostream & = 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 string &);

Query(const Query &c):p(c.p),use(c.use)
{
++ *use;
}
~Query()
{
decr_use();
}
Query &operator=(const Query &);

set<TextQuery::line_no>
eval(const TextQuery &t) const
{
return p -> eval(t);
}

ostream &display(ostream &os) const
{
return p -> display(os);
}

private:
Query(Query_base *query):
p(query),use(new std::size_t(1)) {}

Query_base *p;
std::size_t *use;

void decr_use()
{
if ( -- *use == 0 )
{
delete p;
delete use;
}
}
};

inline Query &
Query::operator=(const Query &rhs)
{
++ * rhs.use;
decr_use();

p = rhs.p;
use = rhs.use;

return *this;
}

inline ostream &
operator<<(ostream &os,const Query &q)
{
return q.display(os);
}

class WordQuery : public Query_base
{
friend class Query;

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

set<line_no> eval(const TextQuery &t) const
{
return t.run_query(query_word);
}
ostream &display(ostream &os) const
{
return os << query_word;
}

string query_word;
};

inline Query::Query(const string &s):
p(new WordQuery(s)),use(new std::size_t(1)) {}

class NotQuery : public Query_base
{
friend Query operator~(const Query &);
NotQuery(Query q):query(q) {}

set<line_no> eval(const TextQuery &) const;

ostream &display(ostream &os) const
{
return os << "~(" << query << ")";
}

const Query query;
};

class BinaryQuery : public Query_base
{
protected:
BinaryQuery(Query left,Query right,string op):
lhs(left),rhs(right),oper(op) {}

ostream &display(ostream &os) const
{
return os << "(" << lhs << " " << oper << " "
<< rhs << ")";
}

const Query lhs,rhs;
const string oper;
};

class AndQuery : public BinaryQuery
{
friend Query operator&(const Query &,const Query &);

AndQuery(Query left,Query right):
BinaryQuery(left,right,"&"){}

set<line_no> eval(const TextQuery &) const;
};

class OrQuery : public BinaryQuery
{
friend Query operator|(const Query &,const Query &);

OrQuery(Query left,Query right):
BinaryQuery(left,right,"|"){}

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 &oper)
{
return new NotQuery(oper);
}

#endif // QUERY_H_INCLUDED

//4 in Query.cpp
#include "Query.h"

set<TextQuery::line_no>
OrQuery::eval(const TextQuery &file) const
{
set<line_no> left = lhs.eval(file),
ret_lines = rhs.eval(file);

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

return ret_lines;
}

set<TextQuery::line_no>
AndQuery::eval(const TextQuery &file) const
{
set<line_no> left = lhs.eval(file),
right = rhs.eval(file);

set<line_no> ret_lines;
set_intersection(left.begin(),left.end(),
right.begin(),right.end(),
inserter(ret_lines,ret_lines.begin()));

return ret_lines;
}

set<TextQuery::line_no>
NotQuery::eval(const TextQuery &file) const
{
set<line_no> hav_val = query.eval(file);
set<line_no> ret_val;

for (line_no n = 0; n != file.size(); ++n)
{
if (hav_val.find(n) == hav_val.end())
{
ret_val.insert(n);
}
}

return ret_val;
}

//5 in main.cpp
//测试数据与前面相同
#include <iostream>
#include <algorithm>
#include "TextQuery.h"
#include "Query.h"

using namespace std;

int main()
{
ifstream inFile("input");

TextQuery file;
file.read_file(inFile);

Query q = Query("fiery") & Query("bird") | Query("wind");

cout << "Executed Query for :" << q << endl;

typedef set<TextQuery::line_no> line_nums;

const line_nums &locs = q.eval(file);

cout << "match occurs " << locs.size()
<< " times" << endl;

line_nums::const_iterator it = locs.begin();
for (; it != locs.end(); ++it)
{
cout << "\t(line " << (*it) + 1 << ") "
<< file.text_line(*it) << endl;
}
}


运行示例:

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