#ifndef TEXTQUERY_H #define TEXTQUERY_H #include #include #include #include #include #include #include #include class QueryResult; class TextQuery { public: using LineNo = std::vector::size_type; TextQuery() = default; TextQuery(std::ifstream &); QueryResult query(const std::string &) const; private: std::shared_ptr> file; std::map>> wm; }; TextQuery::TextQuery(std::ifstream &ifs) : file(new std::vector) { if (ifs) { LineNo n(0); for (std::string line; getline(ifs, line); ++n) { file->push_back(line); std::istringstream iss(line); for (std::string text, word; iss >> text; word.clear()) { std::remove_copy_if(begin(text), end(text), back_inserter(word), ispunct); auto &lines = wm[word]; if (!lines) lines.reset(new std::set); lines->insert(n); } } } else throw std::runtime_error("cannot read file from fstream"); } class QueryResult { friend std::ostream &print(std::ostream &, const QueryResult &); public: QueryResult(const std::string &s, std::shared_ptr> l, std::shared_ptr> f) : sought(s), lines(l), file(f) {} private: std::string sought; std::shared_ptr> lines; std::shared_ptr> file; }; std::ostream &print(std::ostream &os, const QueryResult &qr) { os << "\"" << qr.sought << "\" is in " << qr.lines->size() << " lines.\n"; for (auto n : *qr.lines) os << "\tno." << n + 1 << "\t: " << *(qr.file->begin() + n) << "\n"; return os; } QueryResult TextQuery::query(const std::string &s) const { static std::shared_ptr> nodata(new std::set); auto loc = wm.find(s); if (loc == wm.end()) return QueryResult(s, nodata, file); else return QueryResult(s, wm.at(s), file); } #endif // !TEXTQUERY_H