您的位置:首页 > 编程语言 > C语言/C++

C++ Primer文本查询程序(TextQuery)功能加强版

2014-07-01 09:53 465 查看
  详见书的15.9节。
  面向对象的实现。
一些需要 注意的 地方:
1.#pragma once,在 TextQuery.h文件 中添加,确保其只被编译一次,避免redefinition错误
一些 细节,参照了这位大神的 代码http://blog.csdn.net/hustspy1990/article/details/7296485
先贴 代码,运行起来 似乎 还有些 问题 ,可 再修正

1.TextQuery.h
#pragma once
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>
#include <cstdlib>
using namespace std;
class TextQuery{
public:
 typedef vector<string>::size_type line_no;//是一种别名,类型
 void read_file(ifstream &is)
 {
  store_file(is);//读入并保存文件
  build_map();//创建关联单词和行号的map容器
 }
 set<line_no> run_query(const string&) const;
 string text_line(line_no) const;//行文本
   line_no size() const { return lines_of_text.size(); } //新添加的函数,返回文件的大小
private:
 void store_file(ifstream&);
 void build_map();
 vector<string> lines_of_text;//文件行存储
 map<string,set<line_no>> word_map;//关联容器,单词和文本记录关联
};

2.TextQuery.cpp
#include "TextQuery.h"
using namespace std;
void TextQuery::store_file(ifstream &is)
{
 string textline;
 while (getline(is,textline))
  lines_of_text.push_back(textline);
}
 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;
  while(line>>word)
   word_map[word].insert(line_num);
 }
}
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>();//没有找到,返回空的set集合
 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");
}
string make_plural(size_t ctr,const string &word,const string &ending)//当计数器不为一的时候,返回单词的复数版本
{
 return (ctr==1) ? word: word+ending;
}

3.QueryAll.h
/*C++ Primer文本查询程序*/
#ifndef QUERY_H
#define QUERY_H
#include "TextQuery.h"
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>
#include <cstdlib>
using namespace std;
class Query_base{//虚基类
 friend class Query;
protected:
 typedef TextQuery::line_no line_no;
 virtual ~Query_base(){}
private:
 virtual std::set<line_no> eval(const TextQuery&) const=0;//纯虚函数,该类为虚基类
 virtual ostream& display(ostream& = cout) const=0;
};
class Query{//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&);
 std::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;}//计数为0 ,释放资源
 }
};
//Query输出操作符
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;
};
//NotQuery类
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;
};
//BinaryQuery类
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;
};
//AndQuery类和orQuery类
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重载操作符
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);
}
inline Query::Query(const std::string& word): q(new WordQuery(word)), use(new std::size_t(1)) {}
#endif
4.QueryAll.cpp
#include "QueryAll.h"
#include <map>
#include <iostream>
#include <set>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>
#include <cstdlib>
#include <algorithm>
#include<iterator>
using namespace std;
//OrQuery::eval
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());
 return ret_lines;
}
//AndQuery::eval
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;
}
//NotQUery::eval
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;
}
5.main.cpp
#include "TextQuery.h"
#include <fstream>
#include "QueryAll.h"
using namespace std;
void print_result(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<<(size>1 ? "Times":"Time")<<endl;
 line_nums::const_iterator it = locs.begin();
 for(; it!=locs.end(); ++it)
  cout<<(*it)+1<<"\t"<<file.text_line(*it)<<endl;
}
     
int main()
{
 ifstream is("D:\\Users\\shiwei\\Desktop\\test.txt");
 TextQuery tq;
 tq.read_file(is);
 Query q = Query("The") & Query("of") | Query("the");
 std::set<TextQuery::line_no> locs = q.eval(tq);
 //string s("((fiery & bird) | wind)");
 string s("the & home");
 //string s;
 //cin>>s;
 print_result(locs, s, tq);
 while(true) {
  int i;
  cin>>i;
 };
 return 0;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++