来源:C++ Primer(中文版)(第5版)(第12章)
1、头文件
#ifndef query_h__
#define query_h__
/*
文本查询程序
*/
#include <vector>
#include <set>
#include <map>
#include <memory>
#include <string>
#include <fstream>
#include <iostream>
using std::vector;
using std::map;
using std::set;
using std::shared_ptr;
using std::string;
using std::ifstream;
using std::ostream;
//前置声明
class QueryResult;
//文本查询类
class TextQuery
{
public:
using line_no = vector<string>::size_type;//行号类型
TextQuery(ifstream&);//通过文件流构造
QueryResult query(const string &)const;//查询某个单词的结果
private:
//对于一个文件,容器存储所有行文本
shared_ptr<vector<string>> m_file;
//每个单词映射到它所在的行号的集合
map<string, shared_ptr<set<line_no>>> m_wm;
};
//查询结果类
class QueryResult
{
//打印查询结果,仅声明它是友元,并没有声明这个函数
friend ostream & print(ostream&, const QueryResult&);
using line_no = TextQuery::line_no;
public:
QueryResult(const string &s,
shared_ptr<set<line_no>>p,
shared_ptr<vector<string>> f)
: m_sought(s), m_lines(p), m_file(f)
{}
private:
string m_sought;//查询的单词
shared_ptr<set<line_no>> m_lines;//这个单词出现的行号的集合
shared_ptr<vector<string>> m_file;//在哪个文件中查询这个单词
};
//函数声明 打印查询结果
ostream & print(ostream&, const QueryResult&);
#endif // query_h__
2、源文件
#include "query.h"
#include <sstream>
using std::istringstream;
using std::endl;
TextQuery::TextQuery(ifstream &is)
: m_file(new vector<string>)//分配文件内存
{
string line;//行文本
while (getline(is,line))//获取文件中每一行
{
m_file->push_back(line);//保存
line_no n = m_file->size() - 1;//当前行号
istringstream sin(line);
string word;
while (sin >> word)//获取这一行的每个单词
{
/*
如果单词不在m_wm中,则会作为下标添加到m_wm中,
此时指针会为空
*/
auto &lines = m_wm[word];//shared_ptr<set<line_no>>的引用
if (!lines)//空指针
{
lines.reset(new set<line_no>);//分配内存
}
lines->insert(n);//添加行号
}
}
}
QueryResult TextQuery::query(const string &sought) const
{
auto loc = m_wm.find(sought);//查询单词
if (loc == m_wm.end())//没查询到
{
static shared_ptr<set<line_no>> nodata(new set<line_no>);
return QueryResult(sought, nodata, m_file);
}
else
{
return QueryResult(sought, loc->second, m_file);
}
}
ostream & print(ostream &os, const QueryResult&qr)
{
os << qr.m_sought << " occurs " << qr.m_lines->size()
<< " time(s)" << endl;
//*qr.m_lines:set<line_no>
for (auto num : *qr.m_lines)
{
os << "\t(line " << num + 1 << ") "
/*
qr.m_file : shared_ptr<vector<string>>
qr.m_file->begin() : 第一个vector<string>::iterator
qr.m_file->begin() + num : 第num个vector<string>::iterator
*(qr.m_file->begin() + num) : 解引用这个迭代器
*/
<< *(qr.m_file->begin() + num) << endl;
}
return os;
}
3、实现文件
#include "query.h"
using std::cin;
using std::cout;
using std::endl;
int main()
{
ifstream fin("file.txt");
if (!fin)//打开文件失败
{
return EXIT_FAILURE;
}
TextQuery tq(fin);//文本查询
fin.close();//关闭文件
while (true)
{
cout << "enter word to look for, or q to quit: ";
string s;
if (!(cin >> s) || s == "q")//输入失败,或输入q,则退出
{
break;
}
print(cout , tq.query(s)) //打印查询结果
<< endl;
}
return 0;
}