C++ Primer 第15章例子-文本查询程序

来源:互联网 发布:寒夜知乎 编辑:程序博客网 时间:2024/06/01 09:57

1. Main.cpp

#include "TextQuery.h"#include <fstream>#include "QueryAll.h"using namespace std;void print_result(const set<TextQuery::line_no>& locs, const string& sought, const TextQuery& file){typedef set<TextQuery::line_no> line_nums;line_nums::size_type size = locs.size();cout<<"\n"<<sought<<" 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(){    ifstream is("text.txt");    TextQuery tq;    tq.read_file(is);    Query q = Query("The") & Query("of") | Query("the");    std::set<TextQuery::line_no> locs = q.eval(tq);    string s("((fiery & bird) | wind)");    print_result(locs, s, tq);/*ifstream infile("text.txt");if(!infile){cout<<"No Input File!"<<endl;return -1;}TextQuery tq;tq.read_file(infile);while(true) {cout<<"Enter word to query, or q to quit: ";string s;cin>>s;if(!cin || s=="q")break;set<TextQuery::line_no> locs = tq.run_query(s);print_result(locs, s, tq);}*/while(true) {        int i;        cin>>i;    };return 0;}

2. TextQuery.h

#pragma once#include <iostream>#include <vector>#include <map>#include <set>#include <string>class TextQuery {public:typedef std::vector<std::string>::size_type line_no;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;};

3. TextQuery.cpp

#include "TextQuery.h"#include <fstream>#include <sstream>using namespace std;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>();elsereturn loc->second;}string TextQuery::text_line(line_no line) const{if(line < lines_of_text.size())return lines_of_text[line];return NULL;}

4. QueryAll.h

// Query.h#ifndef QUERY_H#define QUERY_H#include "TextQuery.h"#include <string>#include <set>#include <iostream>#include <fstream>///////////////////////////////////////////////////////////////////////////////////// class QueryBase: private, abstract class acts as a base for concrete query typesclass QueryBase{    friend class Query;protected:    typedef TextQuery::line_no line_no;    virtual ~QueryBase() {}private:    // eval returns the |set| of lines that this Query matches    virtual std::set<line_no> eval(const TextQuery&) const = 0;    virtual std::ostream& display(std::ostream& = std::cout) const = 0;};///////////////////////////////////////////////////////////////////////////////////// class Queryclass Query{    // these operators need access to the QueryBase's constructor    friend Query operator~ (const Query&);    friend Query operator| (const Query&, const Query&);    friend Query operator& (const Query&, const Query&);    public:    // builds a new WordQuery    Query(const std::string&);    // copy control to manage pointers and reference counting    Query(const Query &c): q(c.q), use(c.use) {        ++*use;    }    ~Query() {        decr_use();    }    Query& operator= (const Query&);    // interface functions: will call corresponding QueryBase operations    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 WordQueryclass WordQuery: public QueryBase{    friend class Query; // Query uses the WordQuery constructorprivate:    WordQuery(const std::string &s): query_word(s) { }    // concrete class: WordQuery defines all inherited pure virtual functions    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;    }    std::string query_word; // word for which to search};inline Query::Query(const std::string& word): q(new WordQuery(word)), use(new std::size_t(1)) {}///////////////////////////////////////////////////////////////////////////////////// class NotQueryclass NotQuery: public QueryBase{    friend Query operator~ (const Query &);    NotQuery(const Query &q): query(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 << "~(" << query << ")";    }    const Query query;};///////////////////////////////////////////////////////////////////////////////////// class BinaryQueryclass 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 AndQueryclass 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 OrQueryclass 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);}#endif

4. QueryAll.cpp

// Query.cpp#include "QueryAll.h"#include "TextQuery.h"#include <map>#include <algorithm>using namespace std;set<TextQuery::line_no> NotQuery::eval(const TextQuery &file) const{    // virtual call through the Query handle to eval    set<line_no> has_val = query.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;}


原创粉丝点击