文本查询示例

最近看c++ primer,把15章最后的例子补充完整,贴出来。文本里的标点符号书中没有考虑,我改了改。

#pragma warning(disable : 4786)
#include <iostream>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <fstream>
#include <algorithm>

using namespace std;
class TextQuery{
public:
	typedef vector<string>::size_type line_no;
	TextQuery():size_t(0){}
	void read_file(ifstream &is)
	{	store_file(is);build_map();}
	set<line_no> run_query(const string &) const;
	string text_line(line_no) const;
	line_no size() const {return size_t;}
private:
	void store_file(ifstream &);
	void build_map();
	line_no size_t;
	vector<string> lines_of_text;
	map<string,set<line_no> > word_map;
};

void TextQuery::store_file(ifstream &is)
{
	string textline;
	while(getline(is,textline))
	{
		lines_of_text.push_back(textline);
		size_t++;
	}
}

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;
		string word_str;
		int i;
		while(line >> word)
		{
			if(isalpha(word[0]) && isalpha(word[word.size()-1]))
				word_map[word].insert(line_num);
			else
			{
				i =0;
				while(i < word.size())
				{
					if(isalpha(word[i]))
						word_str.insert(word_str.end(),word[i]);
					i++;
				}
				word_map[word_str].insert(line_num);
				word_str="";//important!!
			}
		}
	}
}

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>();
	else
		return loc->second;
}

string TextQuery::text_line(line_no line) const
{
	if(line<lines_of_text.size())
		return lines_of_text[line];
	throw out_of_range("line number out of range");
}

class Query_base{
	friend class Query;
protected:
	typedef TextQuery::line_no line_no;
	virtual ~Query_base() {}
private:
	virtual set<line_no>
		eval(const TextQuery&) const =0;
	virtual ostream& display(ostream& = cout) const =0;
};

class Query{
	friend Query operator~(const Query&);
	friend Query operator|(const Query&,const Query&);
	friend Query operator&(const Query&,const Query&);
public:
	Query(const string&);
	Query(const Query&c):q(c.q),use(c.use) {++*use;}
	~Query(){decr_use();}
	Query& operator=(const Query&);
	set<TextQuery::line_no>
		eval(const TextQuery &t) const {return q->eval(t);}
	ostream &display(ostream &os) const {return q->display(os);}
private:
	Query(Query_base *query):q(query),use(new size_t(1)){}
	Query_base *q;
	size_t *use;
	void decr_use()
	{if(--*use==0){delete q;delete use;}}
};

inline ostream& operator<<(ostream &os,const Query &q)
{
	return q.display(os);
}


class WordQuery :public Query_base{
	friend class Query;
	WordQuery(const string &s):query_word(s){}
	set<line_no> eval(const TextQuery &t) const
	{return t.run_query(query_word);}
	ostream& display(ostream &os) const
	{return os<<query_word;}
	string query_word;
};

class NotQuery:public Query_base{
	friend Query operator~(const Query &);
	NotQuery(Query q):query(q){}
	set<line_no> eval(const TextQuery&) const;
	ostream& display(ostream &os) const
	{return os<<"~("<<query<<")";}
	const Query query;
};

class BinaryQuery:public Query_base{
protected:
	BinaryQuery(Query left,Query right,string op):
		 lhs(left),rhs(right),oper(op){}
	ostream& display(ostream &os) const
	{return os<<"("<<lhs<<" "<<oper<<" "<<rhs<<")";}
	const Query lhs,rhs;
	const string oper;
};

class AndQuery:public BinaryQuery{
	friend Query operator&(const Query&,const Query&);
	AndQuery (Query left,Query right):BinaryQuery(left,right,"&"){}
	set<line_no>eval(const TextQuery&) const;
};

class OrQuery:public BinaryQuery{
	friend Query operator|(const Query&,const Query&);
	OrQuery(Query left,Query right):BinaryQuery(left,right,"|"){}
	set<line_no> eval(const TextQuery&) const;
};

Query::Query(const string& str):q(new WordQuery(str)),use(new size_t(1)){}

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 &oper)
{
	return new NotQuery(oper);
}


set<TextQuery::line_no>
OrQuery::eval(const TextQuery& file) const
{
	set<line_no> right = rhs.eval(file),
		ret_lines = lhs.eval(file);
	//ret_lines.insert(right.begin(),right.end());
	std::set<line_no>::iterator it = right.begin();
	
	for(; it != right.end(); ++it)
	{
		ret_lines.insert(*it);
	}

	return ret_lines;
}

set<TextQuery::line_no>
AndQuery::eval(const TextQuery& file) const
{
	set<line_no> left = lhs.eval(file),
		right = rhs.eval(file);
	set<line_no> ret_lines;
	set_intersection(left.begin(),left.end(),right.begin(),right.end(),
		inserter(ret_lines,ret_lines.begin()));
	return ret_lines;
}

set<TextQuery::line_no>
NotQuery::eval(const TextQuery& file) const
{
	set<TextQuery::line_no> has_val = query.eval(file);
	set<line_no> ret_lines;
	for(TextQuery::line_no n=0; n != file.size(); ++n)
		if(has_val.find(n) == has_val.end())
			ret_lines.insert(n);
		return ret_lines;
}


ifstream &open_file(ifstream &in,const string &file)
{
	in.close();
	in.clear();
	in.open(file.c_str());
	return in;
}

string make_plural(size_t ctr,const string &word,const string &ending)
{
	return (ctr==1)?word:word+ending;
}

void print_results(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<<" "<<make_plural(size,"time","s")<<endl;

	line_nums::const_iterator it=locs.begin();
	for(;it != locs.end();++it){
		cout<<"\t(line "<<(*it)+1<<") "<<file.text_line(*it)<<endl;
	}
}

void print_more_results(const set<TextQuery::line_no>& locs,const TextQuery &file)
{
	typedef set<TextQuery::line_no> line_nums;
	line_nums::size_type size=locs.size();
	cout<<"\nmatch"<<" occurs "<<size<<" "<<make_plural(size,"time","s")<<endl;

	line_nums::const_iterator it=locs.begin();
	for(;it != locs.end();++it){
		cout<<"\t(line "<<(*it)+1<<") "<<file.text_line(*it)<<endl;
	}
}

int main(int argc,char **argv)
{
	ifstream infile;
	if(argc < 2 || !open_file(infile,argv[1])){
		cerr<<"No input file!"<<endl;
		return EXIT_FAILURE;
	}
	TextQuery tq;
	tq.read_file(infile);
/*	while(true){
		cout<<"enter word to look for ,or q to quit: ";
		string s;
		cin>>s;
		if(!cin || s=="q")	break;
		set<TextQuery::line_no> locs = tq.run_query(s);
		print_results(locs,s,tq);
	}*/
//	Query q = Query("fiery") & Query("bird") | Query("wind");
	Query q =Query("Daddy");
//	Query q =Query("mean");
//	Query q =~Query("Alice");
//	Query q = Query("hair") | Query("Alice");
//	Query q = Query("hair") & Query("Alice");
	cout<<"\nExecuted query: "<<q<<endl;
	print_more_results(q.eval(tq),tq);
	return 0;
}

示例文本:

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值