C++ Primer 第五版 中文版 练习 12.30
题目:定义你自己版本的TextQuery和QueryResult类,并执行12.3.1节中的runQueryies函数。
答:看了书上的两个类的定义,于是下面的代码等于是抄了书上的代码……只不过是让书上的代码能运行了……
由于我用的是 vs 2013 所以头文件中有一个 #pragma once。
TextQuery.h
#pragma once
#include <memory>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <fstream>
#include <sstream>
class QueryResult; //声明类 QueryResult,为了定义query函数的返回类型。
class TextQuery
{
public:
using line_no = std::vector<std::string>::size_type;
TextQuery(std::ifstream&); //构造函数用来生成对象并保存文本和每个单词到它把在的行号的集合的映射。
QueryResult query(const std::string &) const; //查询结果并返回QueryResult对象用于打印。
private:
std::shared_ptr<std::vector<std::string>> file;//输入文件
//每个单词到它把在的行号的集合的映射。
std::map<std::string, std::shared_ptr<std::set<line_no>>> wm;
};
TextQuery.cpp
#include "TextQuery.h"
#include "QueryResult.h"
using namespace std;
//读取输入文件并建立单词到行号的映射
TextQuery::TextQuery(ifstream &is) :file(new vector<string>)
{
string text;
while (getline(is,text)) //对文件中每一行
{
file->push_back(text); //保存此行文本
int n = file->size() - 1; //当前行号
istringstream line(text); //将文本分解为单词
string word;
while (line >> word) //对行中每个单词
{
auto &lines = wm[word]; //如果单词不在wm中,以之为下标在wm中添加一项
if (!lines) //在我们第一次遇到这个单词时,此指针为空
lines.reset(new set<line_no>); //分配一个新的set
lines->insert(n); //将此行号插入set中
}
}
}
QueryResult TextQuery::query(const string &sought) const
{
//如果未找到 sought ,我们将返回一个批向此set的指针
static shared_ptr<set<line_no>> nodata(new set<line_no>);
//使用find 而不是下标运算符来查找单词,避免将单词添加到wm中。
auto loc = wm.find(sought);
if (loc==wm.end())
return QueryResult(sought, nodata, file);//未找到
else
return QueryResult(sought, loc->second, file);
}
QueryResult.h
#pragma once
#include <iostream>
#include <vector>
#include <memory>
#include <set>
#include <string>
class QueryResult
{
friend std::ostream& print(std::ostream&, const QueryResult&);
public:
using line_no = std::vector<std::string>::size_type;
QueryResult(std::string s, std::shared_ptr <std::set<line_no>> p, std::shared_ptr<std::vector<std::string>> f) :
sougth(s), lines(p), file(f) {}
private:
std::string sougth; //查询单词
std::shared_ptr<std::set<line_no>> lines; //出现的行号
std::shared_ptr<std::vector<std::string>> file; //输入文件
};
inline std::string make_plural(std::size_t ctr, const std::string &word, const std::string &ending)
{
return (ctr > 1) ? word + ending : word;
}
QueryResult.cpp
#include "QueryResult.h"
using namespace std;
//在给定的流上打印出给定的QueryResult对象。
ostream &print(ostream &os, const QueryResult &qr)
{
//如果找到了单词,打印出现次数和所有出现的位置
os << qr.sougth << " occurs " << qr.lines->size() << " " << make_plural(qr.lines->size(), "time", "s") << endl;
//打印单词出现的每一行
for (auto num:*qr.lines)
os << "\t(line " << num + 1 << ") " << *(qr.file->begin() + num) << endl;
return os;
}
mymain.cpp
#include "QueryResult.h"
#include "TextQuery.h"
#include <fstream>
using namespace std;
void runQueries(ifstream &infile)
{
TextQuery tp(infile);
while (true)
{
cout << "enter word to look for,or q to quit: ";
string s;
if (!(cin >> s) || s == "q")
break;
print(cout, tp.query(s)) << endl;
}
}
int main()
{
ifstream myinfile("1.txt");
runQueries(myinfile);
return 0;
}