temp

核能气质少年 提交于 2019-11-26 20:10:16

QueryResult.h、TextQuery.h、TextQuery.cpp 和 make_plural.h 同练习 12.27

Query.h

#ifndef TEST_QUERY_H
#define TEST_QUERY_H

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

// abstract class acts as a base class for concrete query types; all members are private
class Query_base {
    friend class Query;

protected:
    typedef TextQuery::line_no line_no; // used in the eval functions
    virtual ~Query_base() {}

private:
    // eval returns the QueryResult that matches this Query
    virtual QueryResult eval(const TextQuery &) const = 0;

    // rep is a string representation of the query
    virtual std::string rep() const = 0;
};

// interface class to manage the Query_base inheritance hierarchy
class Query {
    // these operators need access to the shared_ptr constructor
    friend Query operator~(const Query &);

    friend Query operator|(const Query &, const Query &);

    friend Query operator&(const Query &, const Query &);

public:
    Query(const std::string &);  // builds a new WordQuery

    // interface functions: call the corresponding Query_base operations
    QueryResult eval(const TextQuery &t) const { return q->eval(t); }

    std::string rep() const { return q->rep(); }

private:
    Query(std::shared_ptr<Query_base> query) : q(query) {}

    std::shared_ptr<Query_base> q;
};

inline
std::ostream &
operator<<(std::ostream &os, const Query &query) {
    // Query::rep makes a virtual call through its Query_base pointer to rep()
    return os << query.rep();
}

class WordQuery : public Query_base {
    friend class Query; // Query uses the WordQuery constructor
    WordQuery(const std::string &s) : query_word(s) {}

    // concrete class: WordQuery defines all inherited pure virtual functions
    QueryResult eval(const TextQuery &t) const { return t.query(query_word); }

    std::string rep() const { return query_word; }

    std::string query_word;   // word for which to search
};

inline
Query::Query(const std::string &s) : q(new WordQuery(s)) {}

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

    NotQuery(const Query &q) : query(q) {}

    // concrete class: NotQuery defines all inherited pure virtual functions
    std::string rep() const { return "~(" + query.rep() + ")"; }

    QueryResult eval(const TextQuery &) const;

    Query query;
};

class BinaryQuery : public Query_base {
protected:
    BinaryQuery(const Query &l, const Query &r, std::string s) :
            lhs(l), rhs(r), opSym(s) {}

    // abstract class: BinaryQuery doesn't define eval
    std::string rep() const {
        return "(" + lhs.rep() + " "
               + opSym + " "
               + rhs.rep() + ")";
    }

    Query lhs, rhs;    // right- and left-hand operands
    std::string opSym; // name of the operator
};

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 rep and defines the remaining pure virtual
    QueryResult eval(const TextQuery &) const;
};

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

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

    QueryResult eval(const TextQuery &) const;
};

inline Query operator&(const Query &lhs, const Query &rhs) {
    return std::shared_ptr<Query_base>(new AndQuery(lhs, rhs));
}

inline Query operator|(const Query &lhs, const Query &rhs) {
    return std::shared_ptr<Query_base>(new OrQuery(lhs, rhs));
}

inline Query operator~(const Query &operand) {
    return std::shared_ptr<Query_base>(new NotQuery(operand));
}

std::ifstream &open_file(std::ifstream &, const std::string &);

TextQuery get_file(int, char **);

bool get_word(std::string &);

bool get_words(std::string &, std::string &);

std::ostream &print(std::ostream &, const QueryResult &);

#endif //TEST_QUERY_H

Query.cpp

#include "Query.h"
#include "TextQuery.h"

#include <memory>
using std::shared_ptr;

#include <set>
using std::set;

#include <algorithm>
using std::set_intersection;

#include <iostream>
using std::ostream;

#include <cstddef>
using std::size_t;

#include <iterator>
using std::inserter;

#include <vector>
using std::vector;

#include <string>
using std::string;

// returns the lines not in its operand's result set
QueryResult
NotQuery::eval(const TextQuery &text) const {
    // virtual call to eval through the Query operand
    QueryResult result = query.eval(text);

    // start out with an empty result set
    shared_ptr<set<line_no> > ret_lines(new set<line_no>);

    // we have to iterate through the lines on which our operand appears
    QueryResult::line_it beg = result.begin(), end = result.end();

    // for each line in the input file, if that line is not in result,
    // add that line number to ret_lines
    vector<string>::size_type sz = result.get_file()->size();
    for (size_t n = 0; n != sz; ++n) {
        // if we haven't processed all the lines in result
        // check whether this line is present
        if (beg == end || *beg != n)
            ret_lines->insert(n);  // if not in result, add this line
        else if (beg != end)
            ++beg; // otherwise get the next line number in result if there is one
    }
    return QueryResult(rep(), ret_lines, result.get_file());
}

// returns the intersection of its operands' result sets
QueryResult
AndQuery::eval(const TextQuery &text) const {
    // virtual calls through the Query operands to get result sets for the operands
    QueryResult left = lhs.eval(text), right = rhs.eval(text);

    // set to hold the intersection of left and right
    shared_ptr<set<line_no> > ret_lines(new set<line_no>);

    // writes the intersection of two ranges to a destination iterator
    // destination iterator in this call adds elements to ret
    set_intersection(left.begin(), left.end(),
                     right.begin(), right.end(),
                     inserter(*ret_lines, ret_lines->begin()));
    return QueryResult(rep(), ret_lines, left.get_file());
}

// returns the union of its operands' result sets
QueryResult
OrQuery::eval(const TextQuery &text) const {
    // virtual calls through the Query members, lhs and rhs
    // the calls to eval return the QueryResult for each operand
    QueryResult right = rhs.eval(text), left = lhs.eval(text);

    // copy the line numbers from the left-hand operand into the result set
    shared_ptr<set<line_no> >
            ret_lines(new set<line_no>(left.begin(), left.end()));

    // insert lines from the right-hand operand
    ret_lines->insert(right.begin(), right.end());
    // return the new QueryResult representing the union of lhs and rhs
    return QueryResult(rep(), ret_lines, left.get_file());
}

get_print.cpp

#include "Query.h"
#include "TextQuery.h"

#include <string>
using std::string;

#include <iostream>
using std::cout; using std::cin;

#include <fstream>
using std::ifstream;

#include <stdexcept>
using std::runtime_error;

// these functions are declared in Query.h
TextQuery get_file(int argc, char **argv) {
    // get a file to read from which user will query words
    ifstream infile;
    if (argc == 2)
        infile.open(argv[1]);
    if (!infile) {
        throw runtime_error("No input file!");
    }

    return TextQuery(infile);  // builds query map
}

bool get_word(string &s1) {
    cout << "enter a word to search for, or q to quit: ";
    cin >> s1;
    if (!cin || s1 == "q") return false;
    else return true;
}

bool get_words(string &s1, string &s2) {

    // iterate with the user: prompt for a word to find and print results
    cout << "enter two words to search for, or q to quit: ";
    cin >> s1;

    // stop if hit eof on input or a "q" is entered
    if (!cin || s1 == "q") return false;
    cin >> s2;
    return true;
}

and_orQueryTest.cpp

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

using std::set;
using std::string;
using std::cin; using std::cout; using std::cerr;
using std::endl;

int main(int argc, char **argv)
{
    // gets file to read and builds map to support queries
    TextQuery file = get_file(argc, argv);

    // iterate with the user: prompt for a word to find and print results
    while (true) {
        string sought1, sought2, sought3;
        if (!get_words(sought1, sought2)) break;
        cout << "\nenter third word: " ;
        cin  >> sought3;
        // find all the occurrences of the requested string
        Query q = Query(sought1) & Query(sought2)
                  | Query(sought3);
        cout << "\nExecuting Query for: " << q << endl;
        const QueryResult results = q.eval(file);
        // report matches
        print(cout, results);
    }
    return 0;
}

运行程序前,在 CLion -> Run -> Edit Configurations 下配置 Program arguments 为 ../data

注:../data 即为文件 data 的文件名及其相对路径(是相对于可执行程序所在目录的相对路径)。

并在文件 data 中写入如下内容:

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?"

运行程序,程序执行结果如下所示:

// 运行结果
enter two words to search for, or q to quit: fiery bird

enter third word: wind

Executing Query for: ((fiery & bird) | wind)
((fiery & bird) | wind) occurs 3 times
    (line 2)Her Daddy says when the wind blows
    (line 4)like a fiery bird in flight.
    (line 5)A beautiful fiery bird, he tells her,
enter two words to search for, or q to quit: q

Process finished with exit code 0

下面是 andQueryTest.cpp 和 wordQueryTest.cpp 测试程序及其执行结果:

andQueryTest.cpp

#include "Query.h"
#include "TextQuery.h"

#include <string>
using std::string;

#include <iostream>
using std::cout; using std::endl;

#include <set>
using std::set;

int main(int argc, char **argv) {
    // gets file to read and builds map to support queries
    TextQuery file = get_file(argc, argv);

    do {
        string sought1, sought2;
        // stop if hit eof on input or a "q" is entered
        if (!get_words(sought1, sought2)) break;

        // find all the occurrences of the requested string
        Query andq = Query(sought1) & Query(sought2);
        cout << "\nExecuting query for: " << andq << endl;
        QueryResult results = andq.eval(file);
        // report matches
        print(cout, results);

        results = Query(sought1).eval(file);
        cout << "\nExecuted query: " << Query(sought1) << endl;
        // report matches
        print(cout, results);

        results = Query(sought2).eval(file);
        cout << "\nExecuted query: " << Query(sought2) << endl;
        // report matches
        print(cout, results);
    } while (true);

    return 0;
}
// 运行结果
enter two words to search for, or q to quit: hair Alice

Executing query for: (hair & Alice)
(hair & Alice) occurs 1 time
    (line 1)Alice Emma has long flowing red hair.

Executed query: hair
hair occurs 2 times
    (line 1)Alice Emma has long flowing red hair.
    (line 3)through her hair, it looks almost alive,

Executed query: Alice
Alice occurs 1 time
    (line 1)Alice Emma has long flowing red hair.
enter two words to search for, or q to quit: q

Process finished with exit code 0

wordQueryTest.cpp

#include "Query.h"
#include "TextQuery.h"
#include <string>
#include <vector>
#include <map>
#include <set>
#include <iostream>
#include <fstream>
#include <cctype>
#include <cstring>

using std::set;
using std::string;
using std::map;
using std::vector;
using std::cerr;
using std::cout;
using std::cin;
using std::ifstream;
using std::endl;

int main(int argc, char **argv) {
    TextQuery file = get_file(argc, argv);

    // iterate with the user: prompt for a word to find and print results
    do {
        string sought;
        if (!get_word(sought)) break;

        // find all the occurrences of the requested string
        // define synonym for the line_no set 
        Query name(sought);
        const QueryResult results = name.eval(file);
        cout << "\nExecuting Query for: " << name << endl;

        // report no matches
        print(cout, results) << endl;
    } while (true);  // loop indefinitely; the exit is inside the loop
    return 0;
}
// 运行结果
enter a word to search for, or q to quit: Daddy

Executing Query for: Daddy
Daddy occurs 3 times
    (line 2)Her Daddy says when the wind blows
    (line 7)"Daddy, shush, there is no such thing,"
    (line 10)Shyly, she asks, "I mean, Daddy, is there?"

enter a word to search for, or q to quit: q

Process finished with exit code 0
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!