【C++ Primer】文本查询程序再探
2017-03-05 15:40
423 查看
textquery.h
#ifndef _TEXTQUERY_H
#define _TEXTQUERY_H
#include <iostream>
#include <map>
#include <set>
#include <fstream>
#include <sstream>
#include <memory>
#include <vector>
#include <string>
#include <algorithm>
class QueryResult; //查询结果类
class TextQuery; //文本查询类
using line_no = std::vector<std::string>::size_type;
//查询结果类
class QueryResult
{
friend class TextQuery;
friend std::ostream &operator<<(std::ostream &os, const QueryResult &q);
public:
QueryResult() = default;
QueryResult(std::string q_word, std::shared_ptr<std::set<line_no>> lines,
std::shared_ptr<std::vector<std::string>> word_file) :
q_word_(q_word), lines_(lines), word_file_(word_file) {}
std::set<line_no>::iterator begin();
std::set<line_no>::iterator end();
std::shared_ptr<std::vector<std::string>> get_file();
private:
std::string q_word_; //要查询的单词
std::shared_ptr<std::set<line_no>> lines_; //出现行号的集合
std::shared_ptr<std::vector<std::string>> word_file_; //单词文件
};
//文本查询类
class TextQuery
{
friend class QueryResult;
public:
TextQuery() = default;
TextQuery(std::ifstream &is);
//查询函数
QueryResult query(const std::string &word) const;
private:
std::shared_ptr<std::vector<std::string>> m_file_; //查询的文本
std::map<std::string, std::shared_ptr<std::set<line_no>>> m_word_line_; //每个单词以及它的行号集合
};
//Query_base抽象基类,制定一个标准
class Query_base
{
friend class Query;
protected:
virtual ~Query_base() = default;
private:
//eval返回与当前TextQuery匹配的QueryResult
virtual QueryResult eval(const TextQuery &) const = 0;
//rep表示查询的一个string
virtual std::string rep() const = 0;
};
//接口类,基类包括派生类都可以通过Query来使用,隐藏实现
//Query包装了Query_base
class Query
{
friend Query operator~(const Query &); //非
friend Query operator&(const Query &, const Query &); //与
friend Query operator|(const Query &, const Query &); //或
friend std::ostream &operator<<(std::ostream &os, const Query &query);
public:
Query(const std::string &query_word);
QueryResult eval(const TextQuery &t) const
{
return query_->eval(t);
}
std::string rep() const
{
return query_->rep();
}
private:
//构造函数定义为private,不希望一般用户随便定义Query_base对象。
//注意:友元类可以访问protected和private成员。
Query(std::shared_ptr<Query_base> query) : query_(query) {}
//通过智能指针实现动态绑定
std::shared_ptr<Query_base> query_; //查询
};
//派生类
class WordQuery : public Query_base
{
friend class Query;
WordQuery(const std::string &query_word) : query_word_(query_word) {}
//查询单词
QueryResult eval(const TextQuery &t) const
{
return t.query(query_word_);
}
//查询的一个string
std::string rep() const
{
return query_word_;
}
private:
std::string query_word_; //要查找的单词
};
//无论哪种查询都是建立在WordQuery的根本上,因此 Query的构造函数用一个WordQuery来初始化
inline Query::Query(const std::string &query_word) :
query_(new WordQuery(query_word)) {}
//非查询类
class NotQuery : public Query_base
{
friend Query operator~(const Query &query);
NotQuery(const Query &query) : query_(query) {}
//覆盖纯虚函数
QueryResult eval(const TextQuery &) const override;
std::string rep() const override
{
return "~(" + query_.rep() + ")";
}
private:
Query query_; //查询对象
};
inline Query operator~(const Query &query)
{
return std::shared_ptr<Query_base>(new NotQuery(query));
}
//两个运算符的抽象基类
class BinaryQuery : public Query_base
{
protected:
BinaryQuery(const Query &left, const Query &right, std::string op) :
left_(left), right_(right), op_(op) {}
std::string rep() const override
{
return "(" + left_.rep() + " " + op_ + right_.rep() + ")";
}
//因为eval函数还没有定义,所以BinaryQuery还是抽象类
Query left_; //左操作数
Query right_; //右操作数
std::string op_; //操作符
};
//与操作类
class AndQuery : public BinaryQuery
{
friend Query operator&(const Query &left, const Query &right);
AndQuery(const Query &left, const Query &right) :
BinaryQuery(left, right, "&") {}
QueryResult eval(const TextQuery &t) const;
};
inline Query operator&(const Query &left, const Query &right)
{
return std::shared_ptr<Query_base>(new AndQuery(left, right));
}
//或操作类
class OrQuery : public BinaryQuery
{
friend Query operator|(const Query &left, const Query &right);
OrQuery(const Query &left, const Query &right) :
BinaryQuery(left, right, "|") {}
QueryResult eval(const TextQuery &t) const;
};
inline Query operator|(const Query &left, const Query &right)
{
return std::shared_ptr<Query_base>(new OrQuery(left, right));
}
#endif
textquery.cpp
main.cpp
测试文本 file.txt
#ifndef _TEXTQUERY_H
#define _TEXTQUERY_H
#include <iostream>
#include <map>
#include <set>
#include <fstream>
#include <sstream>
#include <memory>
#include <vector>
#include <string>
#include <algorithm>
class QueryResult; //查询结果类
class TextQuery; //文本查询类
using line_no = std::vector<std::string>::size_type;
//查询结果类
class QueryResult
{
friend class TextQuery;
friend std::ostream &operator<<(std::ostream &os, const QueryResult &q);
public:
QueryResult() = default;
QueryResult(std::string q_word, std::shared_ptr<std::set<line_no>> lines,
std::shared_ptr<std::vector<std::string>> word_file) :
q_word_(q_word), lines_(lines), word_file_(word_file) {}
std::set<line_no>::iterator begin();
std::set<line_no>::iterator end();
std::shared_ptr<std::vector<std::string>> get_file();
private:
std::string q_word_; //要查询的单词
std::shared_ptr<std::set<line_no>> lines_; //出现行号的集合
std::shared_ptr<std::vector<std::string>> word_file_; //单词文件
};
//文本查询类
class TextQuery
{
friend class QueryResult;
public:
TextQuery() = default;
TextQuery(std::ifstream &is);
//查询函数
QueryResult query(const std::string &word) const;
private:
std::shared_ptr<std::vector<std::string>> m_file_; //查询的文本
std::map<std::string, std::shared_ptr<std::set<line_no>>> m_word_line_; //每个单词以及它的行号集合
};
//Query_base抽象基类,制定一个标准
class Query_base
{
friend class Query;
protected:
virtual ~Query_base() = default;
private:
//eval返回与当前TextQuery匹配的QueryResult
virtual QueryResult eval(const TextQuery &) const = 0;
//rep表示查询的一个string
virtual std::string rep() const = 0;
};
//接口类,基类包括派生类都可以通过Query来使用,隐藏实现
//Query包装了Query_base
class Query
{
friend Query operator~(const Query &); //非
friend Query operator&(const Query &, const Query &); //与
friend Query operator|(const Query &, const Query &); //或
friend std::ostream &operator<<(std::ostream &os, const Query &query);
public:
Query(const std::string &query_word);
QueryResult eval(const TextQuery &t) const
{
return query_->eval(t);
}
std::string rep() const
{
return query_->rep();
}
private:
//构造函数定义为private,不希望一般用户随便定义Query_base对象。
//注意:友元类可以访问protected和private成员。
Query(std::shared_ptr<Query_base> query) : query_(query) {}
//通过智能指针实现动态绑定
std::shared_ptr<Query_base> query_; //查询
};
//派生类
class WordQuery : public Query_base
{
friend class Query;
WordQuery(const std::string &query_word) : query_word_(query_word) {}
//查询单词
QueryResult eval(const TextQuery &t) const
{
return t.query(query_word_);
}
//查询的一个string
std::string rep() const
{
return query_word_;
}
private:
std::string query_word_; //要查找的单词
};
//无论哪种查询都是建立在WordQuery的根本上,因此 Query的构造函数用一个WordQuery来初始化
inline Query::Query(const std::string &query_word) :
query_(new WordQuery(query_word)) {}
//非查询类
class NotQuery : public Query_base
{
friend Query operator~(const Query &query);
NotQuery(const Query &query) : query_(query) {}
//覆盖纯虚函数
QueryResult eval(const TextQuery &) const override;
std::string rep() const override
{
return "~(" + query_.rep() + ")";
}
private:
Query query_; //查询对象
};
inline Query operator~(const Query &query)
{
return std::shared_ptr<Query_base>(new NotQuery(query));
}
//两个运算符的抽象基类
class BinaryQuery : public Query_base
{
protected:
BinaryQuery(const Query &left, const Query &right, std::string op) :
left_(left), right_(right), op_(op) {}
std::string rep() const override
{
return "(" + left_.rep() + " " + op_ + right_.rep() + ")";
}
//因为eval函数还没有定义,所以BinaryQuery还是抽象类
Query left_; //左操作数
Query right_; //右操作数
std::string op_; //操作符
};
//与操作类
class AndQuery : public BinaryQuery
{
friend Query operator&(const Query &left, const Query &right);
AndQuery(const Query &left, const Query &right) :
BinaryQuery(left, right, "&") {}
QueryResult eval(const TextQuery &t) const;
};
inline Query operator&(const Query &left, const Query &right)
{
return std::shared_ptr<Query_base>(new AndQuery(left, right));
}
//或操作类
class OrQuery : public BinaryQuery
{
friend Query operator|(const Query &left, const Query &right);
OrQuery(const Query &left, const Query &right) :
BinaryQuery(left, right, "|") {}
QueryResult eval(const TextQuery &t) const;
};
inline Query operator|(const Query &left, const Query &right)
{
return std::shared_ptr<Query_base>(new OrQuery(left, right));
}
#endif
textquery.cpp
#include "textquery.h" //QueryResult std::ostream &operator<<(std::ostream &os, const QueryResult &result) { os << "单词出现了:" << result.lines_->size() << "次\n"; for (line_no i : *result.lines_) { os << " " << "line(" << i + 1 << ") "; os << (*(result.word_file_))[i] << "\n"; } return os; } std::set<line_no>::iterator QueryResult::begin() { return lines_->begin(); } std::set<line_no>::iterator QueryResult::end() { return lines_->end(); } std::shared_ptr<std::vector<std::string>> QueryResult::get_file() { return word_file_; } //TextQuery //构造函数 TextQuery::TextQuery(std::ifstream &is) : m_file_(new std::vector<std::string>) { std::string word; //单词 std::string line; //一行文本 static int i = 0; //行号 while (std::getline(is, line)) { m_file_->push_back(line); //存入vactor<string>的末尾 i = m_file_->size() - 1; //最后一行的行号 std::istringstream ist(line); while (ist >> word) { auto &li = m_word_line_[word]; //单词word所在的行号集 if (!li) { //为空,创建一个set<line_no> li.reset(new std::set<line_no>); } //不为空 li->insert(i); } } } //单词查询 QueryResult TextQuery::query(const std::string &word) const { static std::shared_ptr<std::set<line_no>> nodata(new std::set<line_no>); //指向行号集的指针 auto ret = m_word_line_.find(word); if (ret == m_word_line_.end()) { return QueryResult(word, nodata, m_file_); } else { return QueryResult(word, ret->second, m_file_); } } std::ostream &operator<<(std::ostream &os, const Query &query) { return os << query.rep(); } //NotQuery QueryResult NotQuery::eval(const TextQuery &text) const { auto result = query_.eval(text); //文本查询的结果集合 auto ret_lines = std::make_shared<std::set<line_no>>(); //行号集合 auto begin = result.begin(); auto end = result.end(); auto sz = result.get_file()->size(); //文本总行数 for (std::size_t n = 0; n != sz; ++n) { if (begin == end || *begin != n) { ret_lines->insert(n); } else if (begin != end) { ++begin; } } return QueryResult(rep(), ret_lines, result.get_file()); } //AndQuery QueryResult AndQuery::eval(const TextQuery &text) const { auto left = left_.eval(text); auto right = right_.eval(text); auto ret_lines = std::make_shared<std::set<line_no>>(); //将两个范围的交集写入一个目的迭代器中 //本次调用的目的迭代器向ret_lines添加元素 set_intersection(left.begin(), left.end(), right.begin(), right.end(), inserter(*ret_lines, ret_lines->begin())); return QueryResult(rep(), ret_lines, left.get_file()); } //OrQuery QueryResult OrQuery::eval(const TextQuery &text) const { auto left = left_.eval(text); auto right = right_.eval(text); auto ret_lines = std::make_shared<std::set<line_no>>(left.begin(), left.end()); ret_lines->insert(right.begin(), right.end()); return QueryResult(rep(), ret_lines, left.get_file()); }
main.cpp
#include "textquery.h" int main(int argc, char *argv[]) { std::ifstream is(argv[1]); TextQuery t1(is); std::string word; Query q = Query("fiery") & Query("bird") | Query("wind"); std::cout << q << std::endl; std::cout << q.eval(t1) << std::endl; std::cin.get(); return 0; }
测试文本 file.txt
Alice Emma has long flowing red hair. Her Daddy says when the wind blows through her hair, it looks almost alive, like a fiery bird in flight. A beautiful fiery bird, he tells her, magical but untamed. "Daddy, shush, there is no such thing," she tells him, at the same time wanting him to tell her more. Shyly, she asks, "I mean, Daddy, is there?"
相关文章推荐
- C++ Primer文本查询程序(TextQuery)功能加强版
- 【C++ Primer】【学习笔记】【第十章】关联容器之:文本查询程序
- c++ primer 5ed 15.9文本查询程序再探
- C++ primer 文本查询程序 Query
- 《C++ Primer》读书笔记第十二章-2-动态数组 And 文本查询程序
- C++ Primer 关联容器--容器的综合应用:文本查询程序
- 一个简单的文本查询程序—摘至《C++ Primer》
- c++ primer--容器的综合应用:文本查询程序
- c++ primer习题10.6 文本查询程序
- 一个简单的文本查询程序—摘至《C++ Primer》
- 《C++ Primer 5th》读书笔记4---文本查询程序
- C++ Primer 第15章例子-文本查询程序
- c++ primer( 文本查询程序)
- C++ primer 文本查询程序
- C++ Primer 文本查询程序
- C++ Primer 学习笔记_38_STL实践与分析(12)--容器的综合应用:文本查询程序
- C++ Primer 第五版 文本查询程序
- C++ Primer文本查询程序(TextQuery)的实现(2014.5.24)
- 《c++ primer》文本查询程序和邮件处理程序
- C++ Primer 第5版之文本查询程序类