导航

C++primer 练习12.27

Posted on 2016-04-10 21:51  CSU蛋李  阅读(228)  评论(0编辑  收藏  举报
// 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 = 0;
    //对两个智能指针进行值初始化
    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() > 1 ? "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(-1);
    }
    runQueries(ifs);
    return 0;
}