http://blog.csdn.net/clhposs/article/details/5258325
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <cstddef>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <numeric>
class TextQuery
{
typedef std::map<std::string, std::set<std::size_t> > Type;
public:
void read_file(const std::string &strPath)
{
get_data(strPath);
}
std::string get_str(std::size_t i) const;
std::set<std::size_t> get_lines(const std::string &word);
std::size_t size() const
{
return lines.size();
}
private:
void get_data(const std::string &strPath);
private:
std::vector<std::string> lines;
Type words;
};
void TextQuery::get_data(const std::string &strPath)
{
std::ifstream read(strPath.c_str());
if (!read)
return;
std::string str_line;
std::size_t index = -1;
while (std::getline(read, str_line))
{
++index;
lines.push_back(str_line);
std::istringstream str_word(str_line);
std::string word;
while ( str_word >> word)
{
words[word].insert(index);
}
}
read.close();
}
std::string TextQuery::get_str(std::size_t i) const
{
return lines[i];
}
std::set<std::size_t> TextQuery::get_lines(const std::string &word)
{
return words[word];
}
class Query_Base
{
friend class Query;
protected:
virtual ~Query_Base() { }
private:
virtual std::set<std::size_t> eval(TextQuery &text) = 0;
virtual void display(std::ostream &os = std::cout) = 0;
};
class WordQuery: public Query_Base
{
friend class Query;
private:
WordQuery(const std::string &str): word(str) { }
virtual std::set<size_t> eval(TextQuery &text)
{
return text.get_lines(word);
}
virtual void display(std::ostream &os = std::cout)
{
os << word;
}
std::string word;
virtual ~WordQuery() { }
};
class Query
{
friend Query operator|(const Query &que1, const Query &que2);
friend Query operator&(const Query &que1, const Query &que2);
friend Query operator~(const Query &que);
public:
Query(const std::string &word): p(new WordQuery(word)), use(new std::size_t(1)) { }
Query(const Query &query): p(query.p), use(query.use) { ++*use; }
Query& operator=(const Query &query)
{
++*use;
del_use();
p = query.p;
use = query.use;
}
std::set<std::size_t> eval(TextQuery &text)
{
return p->eval(text);
}
void display(std::ostream& os = std::cout)
{
p->display(os);
}
private:
Query(Query_Base *base): p(base), use(new std::size_t(1)) { }
Query_Base * p;
std::size_t *use;
void del_use()
{
if (--*use == 0)
{
delete p;
delete use;
}
}
};
std::ostream& operator<<(std::ostream& os, Query &que)
{
que.display(os);
return os;
}
class NotQuery: public Query_Base
{
friend Query operator~(const Query &query);
private:
NotQuery(Query que):query(que) { }
virtual std::set<std::size_t> eval(TextQuery &text);
virtual void display(std::ostream &os /* = std::cout */)
{
os << "( ~" << query << " )";
}
Query query;
};
class BinaryQuery: public Query_Base
{
protected:
BinaryQuery(Query lf, Query rh, std::string op): left(lf), right(rh), oper(op) { }
virtual void display(std::ostream &os /* = std::cout */)
{
os << "( " << left << oper << right << " )";
}
Query left;
Query right;
std::string oper;
};
class AndQuery: public BinaryQuery
{
friend Query operator&(const Query &que1, const Query &que2);
private:
AndQuery(Query lf, Query rg): BinaryQuery(lf, rg, "&")
{}
virtual std::set<std::size_t> eval(TextQuery &text);
};
class OrQuery: public BinaryQuery
{
friend Query operator|(const Query &que1, const Query &que2);
private:
OrQuery(Query lf, Query rg): BinaryQuery(lf, rg, "|")
{}
virtual std::set<std::size_t> eval(TextQuery &text);
};
Query operator|(const Query &que1, const Query &que2)
{
return new OrQuery(que1, que2);
}
Query operator&(const Query &que1, const Query &que2)
{
return new AndQuery(que1, que2);
}
Query operator~(const Query &que)
{
return new NotQuery(que);
}
std::set<std::size_t> AndQuery::eval(TextQuery &text)
{
std::set<std::size_t> rg = right.eval(text), lft = left.eval(text);
std::set<std::size_t> sum;
std::set_intersection(rg.begin(), rg.end(), lft.begin(), lft.end(), std::inserter(sum, sum.end()));
return sum;
}
std::set<std::size_t> OrQuery::eval(TextQuery &text)
{
std::set<std::size_t> rg = right.eval(text), lft = left.eval(text);
lft.insert(rg.begin(), rg.end());
return lft;
}
std::set<std::size_t> NotQuery::eval(TextQuery &text)
{
std::set<std::size_t> word_line = query.eval(text), not_line;
for (std::size_t i = 0; i != text.size(); ++i)
{
if (word_line.find(i) == word_line.end())
{
not_line.insert(i);
}
}
return not_line;
}
int main()
{
std::string strPath;
std::cin >> strPath;
TextQuery text;
text.read_file(strPath);
Query find = Query("timeout=3") | Query("[boot");
std::cout << find << std::endl;
std::set<std::size_t> line = find.eval(text);
for (std::set<std::size_t>::iterator iter = line.begin(); iter != line.end(); ++iter)
{
std::cout << "<line " << *iter << ">"<< text.get_str(*iter) << std::endl;
}
system("pause");
return 0;
}