C++ Primer中文本查询示例Query的实现

最近在看C++ Primer复习C++的语法,看到书中15.9章中的文本查询示例时,觉得设计得非常不错,于是便动手照着实现了一个,修改了很久终于运行成功了,从中也学习到了很多的语法。下面把实现与总结分享给大家:

首先是在10.6.2节中实现的TextQuery类:

TextQuery.h

#ifndef __TestC____TextQuery__
#define __TestC____TextQuery__

#include <iostream>
#include <vector>
#include <set>
#include <map>

using namespace std;

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

    TextQuery(string[], vector<string>::size_type);
    set<line_no> run_query(const string&) const;
    line_no size() const;
private:
    vector<string> lines_of_text;
};

#endif /* defined(__TestC____TextQuery__) */

TextQuery.cpp

#include "TextQuery.h"

TextQuery::TextQuery(string strArray[], vector<string>::size_type count) {
    lines_of_text.assign(strArray, strArray+count);
}

set<TextQuery::line_no> TextQuery::run_query(const string&word) const {
    set<line_no> ret_lines;
    for (int i=0;i<lines_of_text.size();i++) {
        string line = lines_of_text[i];
        if (line.find(word) != string::npos) {
            ret_lines.insert(i);
        }
    }
    return ret_lines;
}

TextQuery::line_no TextQuery::size() const {
    return lines_of_text.size();
}

接下来是查询类的句柄类Query:

Query.h

#ifndef __TestC____Query__
#define __TestC____Query__

#include <iostream>
#include "TextQuery.h"

class Query_base;

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 &);
    virtual ~Query();
    Query& operator=(const Query&);

    set<TextQuery::line_no> eval(const TextQuery&) const;
    ostream & display(ostream &) const;
private:
    Query(Query_base *);

    Query_base *q;
    size_t *use;
    void decr_use();
};

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

#endif /* defined(__TestC____Query__) */

Query.cpp

#include "Query.h"
#include "Query_base.h"

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

Query::Query(const string &s) : q(new WordQuery(s)), use(new size_t(1)) {

}

Query::Query(Query_base *query) : q(query), use(new size_t(1)) {

}

Query::~Query() {
    decr_use();
}

void Query::decr_use() {
    if (--*use == 0) {
        delete q;
        delete use;
    }
}

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

ostream& Query::display(ostream &os) const {
    return q->display(os);
}

接下来是最核心的各个查询类Query_base、WordQuery、NotQuery、AndQuery、OrQuery:

Query_base.h

#ifndef __TestC____Query_base__
#define __TestC____Query_base__

#include <iostream>
#include "TextQuery.h"
#include "Query.h"

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 WordQuery : Query_base {
    friend class Query;
    WordQuery(const string &);
    set<line_no> eval(const TextQuery&) const;
    ostream & display(ostream & = cout) const;

    string query_word;
};

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

    NotQuery(Query);
    set<line_no> eval(const TextQuery&) const;
    ostream & display(ostream & = cout) const;
    const Query query;
};

class BinaryQuery : public Query_base {
protected:
    BinaryQuery(Query left, Query right, string op);
    ostream & display(ostream & = cout) const;

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

class AndQuery : BinaryQuery {
    friend Query operator&(const Query&, const Query&);
    AndQuery(Query left, Query right);
    set<line_no> eval(const TextQuery&) const;
};

class OrQuery : BinaryQuery {
    friend Query operator|(const Query&, const Query&);
    OrQuery(Query left, Query right);
    set<line_no> eval(const TextQuery&) const;
};

#endif /* defined(__TestC____Query_base__) */

Query_base.cpp

#include "Query_base.h"

/**
 * WordQuery
 */

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

}

set<WordQuery::line_no> WordQuery::eval(const TextQuery &t) const {
    return t.run_query(query_word);
}

ostream & WordQuery::display(ostream &os) const {
    return os << query_word;
}

/**
 * NotQuery
 */

NotQuery::NotQuery(Query q) : query(q) {

}

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

    for (TextQuery::line_no n = 0; n != file.size(); ++n) {
        if (has_val.find(n) == has_val.end()) {
            ret_lines.insert(n);
        }
    }
    return ret_lines;
}

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

/**
 * BinaryQuery
 */

BinaryQuery::BinaryQuery(Query left, Query right, string op) : lhs(left), rhs(right), oper(op) {

}

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

/**
 * AndQuery
 */

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

}

set<AndQuery::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;
}

/**
 * OrQuery
 */

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

}

set<OrQuery::line_no> OrQuery::eval(const TextQuery&file) const {
    set<line_no> right = rhs.eval(file), ret_lines = lhs.eval(file);
    ret_lines.insert(right.begin(), right.end());
    return ret_lines;
}

下面是以上代码的用法示例:

main.cpp

#include "Query.h"
#include "Query_base.h"

using namespace std;

inline Query operator~(const Query &oper) {
    return new NotQuery(oper);
}

inline Query operator|(const Query &left, const Query &right) {
    return new OrQuery(left, right);
}

inline Query operator&(const Query &left, const Query &right) {
    return new AndQuery(left, right);
}

int main(int argc, const char * argv[])
{
    string article[] = {
        "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?\""
    };

    Query q = ~(Query("fiery") & Query("bird") | Query("wind"));
    set<vector<string>::size_type> result = q.eval(TextQuery(article, sizeof(article)/sizeof(article[0])));
    for (set<vector<string>::size_type>::iterator iter = result.begin(); iter != result.end(); iter++) {
        cout << *iter+1 << endl;
    }
    return 0;
}

以上代码中需要注意的语法点有:

1. Query的几个重载操作符如果作为inline函数的话,必须放在定义的头文件或者用到重载操作符的实现文件中,在本例中如果放在Query.h文件中,由于需要引入Query_base.h文件,会导致头文件循环引用的问题,因此放在了main函数中。<<操作符由于没有使用其他类,所以可以放在Query_base.h文件中。

2. 由于NotQuery、OrQuery、AndQuery几个类的构造函数都是私有的,因此必须将使用到这几个类的函数声明为友元函数,在本例中为&、|、~几个操作符函数。

如果大家觉得对自己有帮助的话,还希望能帮顶一下,谢谢:)

个人博客:http://blog.csdn.net/zhaoxy2850

本文地址:http://blog.csdn.net/zhaoxy_thu/article/details/37995161

转载请注明出处,谢谢!

时间: 2024-11-05 23:19:53

C++ Primer中文本查询示例Query的实现的相关文章

C++ Primer 学习笔记_73_面向对象编程 --再谈文本查询示例

面向对象编程 --再谈文本查询示例 引言: 扩展第10.6节的文本查询应用程序,使我们的系统可以支持更复杂的查询. 为了说明问题,将用下面的简单小说来运行查询: 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

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

面向对象编程 --再谈文本查询示例[续/习题] //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&g

C++ Primer 学习笔记_73_面向对象编程 -再谈文本查询示范

面向对象编程 --再谈文本查询示例 引言: 扩展第10.6节的文本查询应用程序,使我们的系统可以支持更复杂的查询. 为了说明问题,将用下面的简单小说来运行查询: 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

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

面向对象编程 --再谈文本查询示例[续/习题] //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&g

【足迹C++primer】41、文本查询程序

/** * 功能:使用标准库:文本查询程序 * 时间:2014年7月10日09:10:15 * 作者:cutter_point */ #include<iostream> #include<map> #include<set> #include<fstream> #include<sstream> #include<string> #include<vector> #include<memory> using

【足迹C++primer】56、文本查询程序

/** * 功能:文本查询程序 * 时间:2014年7月23日10:26:09 * 作者:cutter_point */ #include<iostream> #include<algorithm> #include<memory> #include<set> #include<map> #include<fstream> #include<sstream> using namespace std; /* Alice Em

C++自学笔记_文本查询程序_《C++ Primer》

<C++ Primer> 第10章结束,用一个文本查询程序结束本章 :) 程序将读取用户指定的任意文本文件,然后允许用户从该文件中查找单词.查询的结果是该单词出现的次数,并列出每次出现所在的行.如果某单词在同一行 中多次出现,程序将只显示该行一次.行号按照升序显示. 程序支持以下任务: · 它必须允许用户指明要处理的文件的名字.程序将存储该文件的内容,以便输出每个单词所在的原始行. · 它必须将每一行分解为各个单词,并记录每个单词所在的行.在输出行号时,应保证以升序输出,并且不重复. · 对特

MongoDB官方C#驱动中查询条件Query用法

http://www.cnblogs.com/viprx/archive/2012/09/06/2673693.html MongoDB条件查询的基本语法. Query.All("name", "a", "b");//通过多个元素来匹配数组  Query.And(Query.EQ("name", "a"), Query.EQ("title", "t"));//同时满足

C++ Primer 学习笔记_38_STL实践与分析(12)--容器的综合应用:文本查询程序

STL 实践与分析 -- 容器的综合应用:文本查询程序 引言: 本章中最重点的实例,因为不需要用到 multiset 与 multimap 的内容,于是将这一小节提到了前面,通过这个实例程序,大师分析问题的智慧,大师的编程风格,大师对程序的控制能力,由此可见一斑.因此,我对这一小节的内容几乎不做修改,或只做很小的更改(因为有些东西不同人有不同的理解),搬出来,以供大家仔细品读. 要求: 我们的程序将读取用户指定的 任意文本文件 , 然后允许用户从该文件中查找单词. 查询的结果是该单词出现的次数