C++ Primer(第五版)第12章例程(文本检索)

前言:最近又开始看起了C++ Primer,第十二章的最后有个文本检索的例程,参考网上的资料把例程写了一下并简单地做了注释。顺带一提,虽然别人都说真正的大佬都是用编辑器+插件来写代码,但是用了一段时间的vim,还是觉得装再多的插件,编辑器始终是编辑器,还是没有ide好用,所以在这台老爷机上装了个codeblocks,除了偶尔死机外,真的极大提高了我的效率,vim的话,还是在命令行模式里再用吧,当然装了插件之后,也还蛮不错的。 

/*********************************************************************************
 **file:TextQuery.h
*********************************************************************************/

#include <string>
#include <memory>
#include <initializer_list>
#include <exception>
#include <vector>
#include <map>
#include <set>

//最好不要在头文件里用using,可能会造成命名错误
using std::vector;
using std::string;
using std::shared_ptr;

class ConstStrBlobPtr;

class StrBlob
{
public:
    using size_type = vector<string>::size_type;            //string类型的vector的类型别名
    friend class ConstStrBlobPtr;                                  //友元类ConstStrBlobPtr可以调用StrBlob的元素

    ConstStrBlobPtr begin() const;                                  //两个迭代器
    ConstStrBlobPtr end() const;

//构造函数
StrBlob():data(std::make_shared<vector<string>>()){ }
StrBlob(std::initializer_list<string> il):data(std::make_shared<vector<string>>(il)){  }

    size_type size() const
    {
        return data->size();
    }

    bool empty() const
    {
        return data->empty();
    }

    void push_back(const string &t)
    {
        data->push_back(t);
    }

    void pop_back()
    {
        check(0, "pop_back on empty StrBlob");
        data->pop_back();
    }

    std::string& front()
    {
        check(0, "front on empty StrBlob");
        return data->front();
    }

    std::string& back()
    {
        check(0, "back on empty StrBlob");
        return data->back();
    }

    const std::string& front() const
    {
         check(0, "front on empty StrBlob");
         return data->front();
    }

    const std::string& back() const
    {
        check(0, "back on empty StrBlob");
        return data->back();
    }


private:
    void check(size_type i, const string &msg) const
    {
        if (i >= data->size())
            throw std::out_of_range(msg);
    }

private:
    std::shared_ptr<vector<string>> data;
};

class ConstStrBlobPtr
{
public:
    //构造函数
    ConstStrBlobPtr():curr(0) { }
    ConstStrBlobPtr(const StrBlob &a, size_t sz = 0) : wptr(a.data), curr(sz) { }

    //重载运算符
    bool operator != (ConstStrBlobPtr& p)
    {
        return p.curr != curr;
    }

    //解引用函数
    const string& deref() const
    {
        auto p = check(curr, "dereference past end");
        return (*p)[curr];
    }

    //递增函数
    ConstStrBlobPtr& incr()
    {
        check(curr, "increment past end of StrBlobPtr");
        ++curr;
        return *this;
    }

private:
    std::shared_ptr<vector<string>> check(size_t i, const string &msg) const
    {
        auto ret = wptr.lock();         //若wptr.use_count()为空,则返回一个空的shared_ptr,否则返回一个指向wptr对象的shared_ptr
        if (!ret)
            throw std::runtime_error("unbound StrBlobPtr");
        if (i >= ret->size())
            throw std::out_of_range(msg);
        return ret;
    }

    std::weak_ptr<vector<string>> wptr;         //存放数据
    size_t curr;                                                //作为位数
};

class QueryResult;
class TextQuery
{
public:
    TextQuery(std::ifstream &);                 //保存文件数据
    QueryResult query(const string&) const;

private:
    StrBlob file;               //保存文件数据
    std::map<string, shared_ptr<std::set<StrBlob::size_type>>> result;
};

class QueryResult
{
public:
    //set的迭代器
    using ResultIter = std::set<StrBlob::size_type>::iterator;
    //友元函数,起输出作用
    friend std::ostream& print(std::ostream &, const QueryResult&);

public:
    //构造函数
    QueryResult(const string &s, shared_ptr<std::set<StrBlob::size_type>> set, const StrBlob& f) : word(s), nos(set), file(f) { }
    //迭代器
    ResultIter begin() const {return nos->begin();}
    ResultIter end() const {return nos->end();}
    shared_ptr<StrBlob> get_file() const {return std::make_shared<StrBlob>(file);}

private:
    string word;                //保存输入的搜索词
    shared_ptr<std::set<StrBlob::size_type>> nos;               //某个词对应的行数集合set
    StrBlob file;               //保存文件数据
};

std::ostream& print(std::ostream &, const QueryResult&);

 

/*************************************************************************
 **file:TextQuery.cpp
*************************************************************************/

#include "TextQueryClassHeader.h"
#include <sstream>
#include <algorithm>
#include <iostream>
#include <fstream>

//TextQuery类构造函数:实现分词,统计的功能
TextQuery::TextQuery(std::ifstream &ifs)
{
    StrBlob::size_type lineNo{ 0 };
    for (string line; std::getline(ifs, line); ++lineNo)
    {
        file.push_back(line);           //将每一行的文本保存到vector类型的shared_ptr中
        std::istringstream line_stream(line);       //分词,保存在line_stream

        //将每个单词添加到map中进行统计
        //word保存关键词,text保存已分词的某一行文本
        for(string text, word; line_stream >> text; word.clear())
        {
            //如果是标点符号,则去除
            std::remove_copy_if(text.begin(), text.end(), std::back_inserter(word), ispunct);

            //将每一个单词录入map中,如果单词之前不存在,则申请一块空间
            auto &nos = result[word];
            if (!nos)
                nos.reset(new std::set<StrBlob::size_type>);
            nos->insert(lineNo);
        }
    }
}

//查询行数函数
QueryResult TextQuery::query(const string& str) const
{
    //分配内存
    static shared_ptr<std::set<StrBlob::size_type>> nodata(new std::set<StrBlob::size_type>);

    auto found = result.find(str);

    //如果要查询的单词不在map中,返回空白内存
    if (found == result.end())
        return QueryResult(str, nodata, file);
    else
        return QueryResult(str, found->second, file);
}

//打印函数
std::ostream& print(std::ostream &out, const QueryResult& qr)
{
    out << qr.word << " occurs " << qr.nos->size() << (qr.nos->size() > 1 ? "times" : "time") << std::endl;
    for (auto i : *qr.nos)
    {
        ConstStrBlobPtr p(qr.file, i);
        //set的下标从0开始,为了更符合阅读习惯,自动加1
        out << "\t(line " << i  + 1 << " ): " << p.deref() << std::endl;
    }
    return out;
}

//调用入口
void runQueries(std::ifstream &infile)
{
    //在此处分词统计已经完成
    TextQuery tq(infile);
    do
    {
        std::cout << "enter word to look for, or q to quit: ";
        string s;
        if (!(std::cin >> s) || s == "q")
            break;
        print(std::cout, tq.query(s)) << std::endl;
    }while(true);
}

//主函数
int main()
{
    std::ifstream file("../poetry.txt");
    runQueries(file);
}

 

/*******************************************************************************
 **file:Text file for test
*******************************************************************************/

1. Mistakes - Zheng Chou Yu
I beat Jiangnan
The face waiting in the season is like the opening and falling of lotus
If the east wind does not come, the catkins in March will not fly
Your heart is like a little lonely city
Just like the street of bluestone is getting late
The spring curtain of March will not be revealed
Your heart is a little window
My dada's hooves are a beautiful mistake
I'm not back, I'm a passer-by
2. Chapter break Bian Zhilin
You stand on the bridge to see the scenery,
The people who look at the scenery are looking at you upstairs.
The moon decorates your window,
You decorate other people's dreams.
3. A generation Gu Cheng
Night gives me black eyes
I use it to find light
4. Don't - Gu Cheng
In spring,
I flicked my handkerchief,
Let me go away,
Or return now?
No, nothing,
It's nothing,
Like falling flowers in the water,
Like dew on flowers
Only the shadow knows,
Only wind energy experience,
Only the butterfly that sighs and starts,
Still flying in my heart
5. Far and near Gu Cheng
You,
Look at me later,
Look at the clouds later.
I think,
You see me far away,
You look close to the clouds.
6. I love this land - Ai Qing
If I were a bird,
I should also sing with my hoarse throat:
The land that was hit by the storm,
The river of our indignation is surging forever,
The wind of wrath that blows endlessly,
And the gentle dawn from the forest
——And then I died,
Even feathers rot in the ground.
Why do my eyes often contain tears?
Because I love this land deeply
7. Weight - Han Han
She took the bloody head,
On the balance of life,
Let all those who live,
All lost.
——Weight.
8. Shajanara - Xu Zhimo
It's the tenderness of the bow,
It's like a water lotus, too shy for the cool wind,
One word of treasure, one word of treasure,
There is sweet sorrow in that treasure -
Shajanara!
9. Chance - Xu Zhimo
I am a cloud in the sky,
Occasionally projected on your wave heart
You don't have to be surprised,
No need to be happy,
In a twinkling of an eye.
You and I meet in the sea of night,
You have yours, I have mine, direction;
Do you remember,
Better you forget,
The light of the meeting!
10. Alley Gucheng
Alley
Bent and long
No door
No windows
I have an old key
Knocking on the thick wall
11. Arc - Gu Cheng
Birds in the wind
Rapid steering
Teenagers go to pick it up
A penny
Grapevine fantasy
And the extended tentacles
The waves recede
And the rising back

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值