- TextQuery.h
#ifndef TEXTQUERY_H
#define TEXTQUERY_H
#include <memory>
#include <vector>
#include <set>
#include <string>
#include <map>
#include <iostream>
using std::cout;
//读入并解析文件,将解析结果存入QueryResult对象中
class QueryResult;
class TextQuery
{
using _line_no = std::vector<std::string>::size_type;
public:
//根据输入文件流将代查询文件按行存储到vector中并使用shared_ptr进行托管;建立每个单词和所在行数的对应关系,同样使用shared_ptr进行资源托管
TextQuery(std::ifstream&);
//根据单词和所在行的对应关系返回查询结果对象
QueryResult query(const std::string&)const;
private:
//使用shred_ptr减少数据间进行复制次数,整个程序只有一份vector<string>存储查询文件;只有一份单词对应行数set<_lie_no>的存储
//将每一行作为vector的一个元素进行存储
std::shared_ptr<std::vector<std::string>>_file;
//存储每个单词和对应的行号
std::map<std::string,
std::shared_ptr<std::set<_line_no>>>_wm;
static std::string cleanup_str(const std::string &);
};
#endif // TEXTQUERY_H
- QueryResult.h
#ifndef QUERYRESULT_H
#define QUERYRESULT_H
#include <string>
#include <set>
#include <vector>
#include <memory>
using std::vector;
using std::set;
using std::string;
using std::shared_ptr;
class QueryResult
{
public:
using _lineno = std::vector<std::string>::size_type;
QueryResult(const string &sought,
const shared_ptr<vector<string>>&file,
const shared_ptr<set<_lineno>>&lines)
:_sought(sought)
,_file(file)
,_lines(lines)
{
};
set<_lineno>::size_type size(){return _lines->size();}
//重载输出流函数输出QueryResult对象
friend std::ostream& operator<<(std::ostream&,const QueryResult&);
private:
std::string _sought;
std::shared_ptr<std::vector<std::string>> _file;
std::shared_ptr<std::set<_lineno>> _lines;
};
#endif
- TextQuery.cpp
#include "TextQuery.h"
#include "QueryResult.h"
#include "make_pluarl.h"
#include <fstream>
#include <sstream>
#include <string>
#include <iostream>
using std::string;
using std::vector;
using std::set;
using std::shared_ptr;
using std::endl;
TextQuery::TextQuery(std::ifstream& file)
:_file(new std::vector<std::string>()){
std::string line_text;
int line_no;
//std::istringstream line;
std::string word;
while(std::getline(file,line_text)){
_file->push_back(line_text);
line_no = _file->size()-1;
std::istringstream line(line_text);//初始化
while(line>>word){
word = cleanup_str(word);
auto& no = _wm[word];
if(!no)
no.reset(new std::set<_line_no>);
no->insert(line_no);
}
}
}
QueryResult TextQuery::query(const std::string& sought)const{
static shared_ptr<set<_line_no>> nodata(new set<_line_no>);
auto it = _wm.find(cleanup_str(sought));
if(it==_wm.end()){
//查找的单词不存在
return QueryResult(sought,_file,nodata);
}else{
//找到查找单词
return QueryResult(sought,_file,it->second);
}
}
std::string TextQuery::cleanup_str(const std::string&word){
string ret;
for(auto it = word.begin();it!=word.end();++it){
if(!ispunct(*it))
ret += tolower(*it);
}
return ret;
}
std::ostream & operator<<(std::ostream& os,const QueryResult& qr){
os<<qr._sought<<" occur "<<qr._lines->size()<<" "
<<make_pluarl(qr._lines->size(),"line","s")<<"\n";
for(auto num : *qr._lines){
os<<"\t(line: "<<num+1<<"): "
<<*(qr._file->begin()+num)<<endl;
}
return os;
}
- make_pluarl.h
//判断函数是否为复数,如果是复数就加‘s’
#ifndef MAKE_PLUARL_H_INCLUDED
#define MAKE_PLUARL_H_INCLUDED
#include <string>
//判断行数是不是复数
inline
std::string make_pluarl(size_t ctr, std::string word,std::string ending ){
return (ctr==1)? word : word+ ending;
}
#endif
- main.cpp
#include "TextQuery.h"
#include "QueryResult.h"
#include "make_pluarl.h"
#include <fstream>
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
int main()
{
string filename ="./test.txt";
std::ifstream inputfile(filename);
TextQuery text(inputfile);
while(true){
cout << "Enter word to look for, or q to quit: ";
string sought;
if(!(std::cin>>sought)||sought=="q")
break;
cout<<text.query(sought)<<endl;
}
return 0;
}
所求结果为查询单词所在的行数而不是所出现的次数。
没有使用书中的print函数打印QueryResult对象,重载operator<<函数进行打印。