C++primer 练习12.27

时间:2023-12-20 16:26:50
// 12_27.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include<iostream>
#include<memory>
#include<string>
#include<vector>
#include<fstream>
#include<sstream>
#include<map>
#include<set>
using namespace std; //提前声明类QueryResult,在书中说必须提前声明,然而vs2015中
//仅声明友元类亦可
class QueryResult; class TextQuery
{
//友元类的声明
friend class QueryResult;
public:
//构造函数
TextQuery(ifstream &is);
//返回查询的结果
QueryResult query(string s); private:
//用智能指针来保存数据,实现共享
shared_ptr<vector<string>> vecPtr;
shared_ptr<map<string, set<unsigned>>> mapPtr;
}; //TextQuery的构造函数
TextQuery::TextQuery(ifstream &is)
{
//用来暂存每一行的字符串
string word;
//记录行数
unsigned lineNum = ;
//对两个智能指针进行值初始化
vecPtr = shared_ptr<vector<string>>(new vector<string>());
mapPtr = shared_ptr<map<string, set<unsigned>>>(new map<string, set<unsigned>>());
while (getline(is, word))
{
//将每一行保存在类中
vecPtr->push_back(word);
istringstream iss(word);
string str;
while (iss >> str)
{
//将单词所在的行数记录下来
(*mapPtr)[str].insert(lineNum);
}
++lineNum;
}
} class QueryResult
{
public:
//QueryResult的构造函数,vecPtr实现共享
QueryResult(TextQuery &tq, string &s) :vecPtr(tq.vecPtr)
{
//mapPtr指针的值初始化
mapPtr = shared_ptr<map<string, set<unsigned>>>(new map<string, set<unsigned>>());
//将要查询的单词的结果保存下来
mapPtr->insert(pair<string, set<unsigned>>(s, (*tq.mapPtr)[s]));
}
//有缘函数,实现输出
friend ostream& print(ostream&,const QueryResult &qr);
private:
shared_ptr<vector<string>> vecPtr;
shared_ptr<map<string, set<unsigned>>> mapPtr;
}; //QueryResult的友元函数,实现输出
ostream& print(ostream &os,const QueryResult &qr)
{
//输出这个单词出现了多少次
os << (*qr.mapPtr).cbegin()->first << " occurs " << (*qr.mapPtr).cbegin()->second.size() <<
((*qr.mapPtr).cbegin()->second.size() > ? "times" : "time") << endl;
//输出单词所在的行数,和这一行的字符串
for (auto &e : qr.mapPtr->cbegin()->second)
os << "(line " << e << " ) " << (*qr.vecPtr)[e] << endl;
return os;
} //实现查询的函数
QueryResult TextQuery::query(string s)
{
return QueryResult(*this, s);
} void runQueries(ifstream &infile)
{
TextQuery tq(infile);
while (true)
{
cout << "enter word to look for,or q to quit: ";
string s;
if (!(cin >> s) || s == "q")break;
print(cout, tq.query(s)) << endl;
}
} int main()
{
ifstream ifs("D:\\file\\12_27.txt");
if (!ifs)
{
cerr << "open file failed!" << endl;
exit(-);
}
runQueries(ifs);
return ;
}