#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <iterator>
using namespace std;
class TextQuery {
public:
truetypedef vector<string>::size_type line_no;
truevoid read_file_with_lines(ifstream &is) { store_file_with_lines(is); build_map(); }
truevoid read_file_with_sentences(ifstream &is) { store_file_with_sentences(is); build_map(); }
trueset<line_no> run_query(const string&) const;
truestring text_line(line_no) const;
trueline_no size() const { return lines_of_text.size(); }
private:
truevoid store_file_with_lines(ifstream&);
truevoid store_file_with_sentences(ifstream&);
truevoid build_map();
truevector<string> lines_of_text;
truemap< string, set<line_no> > word_map;
};
void TextQuery::store_file_with_lines(ifstream &is)
{
truestring text_line;
truewhile (getline(is, text_line))
truetruelines_of_text.push_back(text_line);
}
void TextQuery::store_file_with_sentences(ifstream &is)
{
truechar ws[] = { '\t', '\r', '\v', '\f', '\n' };
truechar eos[] = { '?', '.', '!' };
trueset<char> white_space(ws, ws + 5);
trueset<char> end_of_sentences(eos, eos + 3);
truestring sentence;
truechar ch;
truewhile (is.get(ch)) {
truetrueif (!white_space.count(ch))
truetruetruesentence += ch;
truetrueif (end_of_sentences.count(ch)) {
truetruetruelines_of_text.push_back(sentence);
truetruetruesentence.assign("");
truetrue}
true}
}
void TextQuery::build_map()
{
truefor (line_no line_num = 0; line_num != lines_of_text.size(); ++line_num) {
truetrueistringstream line(lines_of_text[line_num]);
truetruestring word;
truetruewhile (line >> word)
truetruetrueword_map[word].insert(line_num);
true}
}
set<TextQuery::line_no> TextQuery::run_query(const string &query_word) const
{
truemap< string, set<line_no> >::const_iterator loc = word_map.find(query_word);
trueif (loc == word_map.end())
truetruereturn set<line_no>();
trueelse
truetruereturn loc->second;
}
string TextQuery::text_line(line_no line) const
{
trueif (line < lines_of_text.size())
truetruereturn lines_of_text[line];
truethrow out_of_range("line number out of range");
}
class Query_base {
truefriend class Query;
protected:
truetypedef TextQuery::line_no line_no;
truevirtual ~Query_base() { }
private:
truevirtual set<line_no> eval(const TextQuery&) const = 0;
truevirtual ostream& display(ostream& = cout) const = 0;
};
class WordQuery : public Query_base {
truefriend class Query;
trueWordQuery(const string &s) : query_word(s) { }
trueset<line_no> eval(const TextQuery &t) const { return t.run_query(query_word); }
trueostream& display(ostream &os) const { return os << query_word; }
truestring query_word;
};
class Query {
true
true
truefriend Query operator~(const Query &);
truefriend Query operator|(const Query &, const Query &);
truefriend Query operator&(const Query &, const Query &);
public:
trueQuery(const string &s) : q(new WordQuery(s)), use(new size_t(1)) { }
trueQuery(const Query &c) : q(c.q), use(c.use) { ++*use; }
true~Query() { decr_use(); }
trueQuery& operator=(const Query&);
trueset<TextQuery::line_no> eval(const TextQuery &t) const { return q->eval(t); }
trueostream& display(ostream &os) const { return q->display(os); }
private:
trueQuery(Query_base *query) : q(query), use(new size_t(1)) { }
trueQuery_base *q;
truesize_t *use;
truevoid decr_use() { if (--*use == 0) { delete q; delete use; } }
};
inline ostream& operator<<(ostream &os, const Query &q)
{
truereturn q.display(os);
}
class NotQuery : public Query_base {
truefriend Query operator~(const Query&);
trueNotQuery(Query q) : query(q) { }
trueset<line_no> eval(const TextQuery&) const;
trueostream& display(ostream &os) const { return os << "~(" << query << ")"; }
trueconst Query query;
};
set<TextQuery::line_no> NotQuery::eval(const TextQuery &file) const
{
trueset<line_no> has_val = query.eval(file);
trueset<line_no> ret_lines;
truefor (line_no n = 0; n != file.size(); ++n)
truetrueif (has_val.find(n) == has_val.end())
truetruetrueret_lines.insert(n);
truereturn ret_lines;
}
class BinaryQuery : public Query_base {
protected:
trueBinaryQuery(Query left, Query right, string op) : lhs(left), rhs(right), oper(op) { }
trueostream& display(ostream &os) const { return os << "(" << lhs << " " << oper << " " << rhs << ")"; }
trueconst Query lhs, rhs;
trueconst string oper;
};
class AndQuery : public BinaryQuery {
truefriend Query operator&(const Query&, const Query&);
trueAndQuery(Query left, Query right) : BinaryQuery(left, right, "&") { }
trueset<line_no> eval(const TextQuery&) const;
};
set<TextQuery::line_no> AndQuery::eval(const TextQuery &file) const
{
trueset<line_no> left = lhs.eval(file), right = rhs.eval(file);
trueset<line_no> ret_lines;
trueset_intersection(left.begin(), left.end(), right.begin(), right.end(), inserter(ret_lines, ret_lines.begin()));
truereturn ret_lines;
}
class OrQuery : public BinaryQuery {
truefriend Query operator|(const Query&, const Query&);
trueOrQuery(Query left, Query right) : BinaryQuery(left, right, "|") { }
trueset<line_no> eval(const TextQuery&) const;
};
set<TextQuery::line_no> OrQuery::eval(const TextQuery &file) const
{
trueset<line_no> right = rhs.eval(file), ret_lines = lhs.eval(file);
trueret_lines.insert(right.begin(), right.end());
truereturn ret_lines;
}
inline Query operator~(const Query &oper)
{
true
true
truereturn new NotQuery(oper);
}
inline Query operator|(const Query &lhs, const Query &rhs)
{
truereturn new OrQuery(lhs, rhs);
}
inline Query operator&(const Query &lhs, const Query &rhs)
{
truereturn new AndQuery(lhs, rhs);
}
ifstream& open_file(ifstream &in, const string &file)
{
truein.close();
truein.clear();
truein.open(file.c_str());
truereturn in;
}
string make_plural(size_t ctr, const string &word, const string &ending) {
truereturn (ctr == 1) ? word : word + ending;
}
void print_result(const set<TextQuery::line_no> results, const Query &sought, const TextQuery &file)
{
truetypedef set<TextQuery::line_no> line_nums;
trueline_nums::size_type size = results.size();
truecout << "\n" << sought << " occurs " << size << " " << make_plural(size, "time", "s") << endl;
truefor (line_nums::const_iterator it = results.begin(); it != results.end(); ++it) {
truetruecout << "\t(line " << (*it) + 1 << ") " << file.text_line(*it) << endl;
true}
}
int main(int argc, char **argv)
{
trueifstream infile;
trueif (argc < 2 || !open_file(infile, argv[1])) {
truetruecerr << "No input file!" << endl;
truetruesystem("pause");
truetruereturn EXIT_FAILURE;
true}
trueTextQuery tq;
truetq.read_file_with_sentences(infile);
trueQuery andq = Query("I") | Query("at");
truecout << "\nExecuted Query For: " << andq << endl;
trueset<TextQuery::line_no> results = andq.eval(tq);
trueprint_result(results, andq, tq);
truesystem("pause");
truereturn 0;
}