C++ Primer书上这个例子讲的很不错,写写帮助自己理解标准库和智能指针。

.h 文件内容

#include <fstream>
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <sstream>
#include <memory> class QueryResult; class TextQuery { public: using line_no = std::vector<std::string>::size_type; TextQuery(std::ifstream& ifs); // 返回string的信息
QueryResult query(const std::string&) const; private: std::shared_ptr<std::vector<std::string>> words_file;
std::map<std::string, std::shared_ptr<std::set<line_no>>> wm; }; class QueryResult { friend std::ostream& print(std::ostream&, const QueryResult&);
public: QueryResult(std::string s, std::shared_ptr<std::vector<std::string>> wf, std::shared_ptr<std::set<size_t>> l) : sought(s), file(wf), lines(l){} private:
std::string sought; // 要查询的单词
std::shared_ptr<std::vector<std::string>> file; // 输入文件
std::shared_ptr<std::set<size_t>> lines; // 保存出现的行号 };

.cpp 文件内容

#include "TextQuery.h"

TextQuery::TextQuery(std::ifstream& ifs) : words_file(new std::vector<std::string>)
{
std::string text;
while (getline(ifs, text)){ words_file->push_back(text);
// 记录当前行号
size_t n = words_file->size() - 1; // 获取每行每个单词
std::istringstream line(text);
std::string word;
while (line >> word){ auto &ckeck = wm[word];
if (nullptr == ckeck)
ckeck.reset(new std::set<line_no>); ckeck->insert(n); }
} } QueryResult TextQuery::query(const std::string& s) const { // 保存一个静态对象 如果未能找到单词,返回此对象
static std::shared_ptr<std::set<size_t>> nodata(new std::set<size_t>); auto location = wm.find(s); if (location == wm.end())
return QueryResult(s, words_file, nodata);
else
return QueryResult(s, words_file, location->second);
} std::ostream& print(std::ostream& os, const QueryResult& qr){ os << qr.sought << " occurs " << qr.lines->size() << " "
<< (qr.lines->size() > 1 ? "times" : "time") << std::endl; for (auto num : *qr.lines)
os << "\t(line " << num + 1 << ")"
<< *(qr.file->begin() + num) << std::endl;
return os;
}

将TextQuery的word_file成员和wm的值set都放在智能指针内,以便QueryResult类可以在正常访问。

TextQuery类:

TextqUuery的构造函数接受一个ifstream,用来读取文件,构造函数的初始化列表中,并且将word_file初始化为一个空的vector, getline从文件中读取一行存入string text中,首先将这一行的内容储存在word_file中,然后计算该行的行号,即就是word_file的大小size() - 1,istringstream对象用来读取string text中的每个单词,如果单词不在wm中,将这个单词对应的set申请一个新的内存空间, 然后将这个单词存入wm的string中,并将它所在的行号存入wm的set中,如果这个单词存在wm中,即使这个单词是第二次或第二次之后出现在同一行,lines->insert(n)并不会执行,因为set不允许重复关键字出现。

QueryResult类中,print函数将查找到的结果输出到屏幕。

QueryResult的构造函数接受一个string,一个shared_ptr,类型为set<size_t>, 还有一个shared_ptr,类型为vector<string>,参数string表示要查询的单词,sett的shared_ptr指向TextQuery的wm中的set,vector的shared_ptr指向TextQuery中的word_file。

TextQuerty中的query函数接受一个string,表示要查询的单词,在函数里声明了一个静态智能指针类型,用来表示未找到单词的set,表示没有该单词的行数可显示,然后在wm中查找该单词。

print函数用于打印给定的QueryResult对象:如果找到了单词,先打印这个单词和出现的次数,qr.lines->size();表示这个set的大小,即就是表示这个单词出现的次数;

然后在for循环中,num依次获取到这个单词出现的行数,由于我们习惯从1开始计数,因此将num + 1;然后在file中找到这一行的数据,*(qr.file->begin() + num), 从file这个vector的首元素开始向后便宜num个元素,即就是我们这个单词出现的那一行,然后我们解引用获得这给一行的string,并将它打印出来。

C++ Primer : 第十二章 : 文本查询程序的更多相关文章

  1. 【WPF学习】第二十二章 文本控件

    WPF提供了三个用于输入文本的控件:TextBox.RichTextBox和PasswordBox.PasswordBox控件直接继承自Control类.TextBox和RichTextBox控件间接 ...

  2. C++ Primer : 第十二章 : 动态内存之unique_ptr和weak_ptr

    unique_ptr 一个unique_ptr拥有它所管理的对象,与shared_ptr不同,unique_ptr指向的对象只能有一个用户.当unique_ptr被销毁后,它所指向的对象也被销毁. 定 ...

  3. C++Primer 第十二章

    //1.标准库提供了两种智能指针类型来管理动态对象,均定义在头文件memory中,声明在std命名空间. // shared_ptr:允许多个指针指向同一个对象. // unique_ptr:独占所指 ...

  4. C++ Primer : 第十二章 : 动态内存之allocator类

    标准库allocator类定义在头文件 <memory>中.它帮助我们将内存分配和构造分离开来,它分配的内存是原始的.未构造的. 类似vector,allocator也是一个模板类,我们在 ...

  5. C++ Primer : 第十二章 : 动态内存之动态数组

    动态数组的分配和释放 new和数组 C++语言和标准库提供了一次分配一个对象数组的方法,定义了另一种new表达式语法.我们需要在类型名后跟一对方括号,在其中指明要分配的对象的数目. int* arr ...

  6. C++ Primer : 第十二章 : 动态内存之shared_ptr与new的结合使用、智能指针异常

    shared_ptr和new结合使用 一个shared_ptr默认初始化为一个空指针.我们也可以使用new返回的指针来初始化一个shared_ptr: shared_ptr<double> ...

  7. C++ Primer : 第十二章 : 动态内存之动态内存管理(new和delete)

    C++语言定义了两个运算符来分配和释放动态内存:运算符new分配内存,运算符delete释放new分配的内存. 运算符new和delete 使用new动态分配和初始化对象 在自由空间分配的内存是无名的 ...

  8. C++ Primer : 第十二章 : 动态内存之shared_ptr类实例:StrBlob类

    StrBlob是一个管理string的类,借助标准库容器vector,以及动态内存管理类shared_ptr,我们将vector保存在动态内存里,这样就能在多个对象之间共享内存. 定义StrBlob类 ...

  9. C++ Primer : 第十二章 : 动态内存之shared_ptr类

    在C++中,动态内存是的管理是通过一对运算符来完成的:new  ,在动态内存中为对象分配空间并返回一个指向该对象的指针,delete接受一个动态对象的指针,销毁该对象,并释放该对象关联的内存. 动态内 ...

随机推荐

  1. linux修改系统时间和linux查看时区、修改时区的方法

    一.查看和修改Linux的时区 1. 查看当前时区命令 : "date -R" 2. 修改设置Linux服务器时区方法 A命令 : "tzselect" 方法 ...

  2. hibernate框架

    在之前的DAO开发中,对关系型数据库进行增删改查都是直接通过sql语句,需要人工的进行对象和表之间的转换.而Hibernate提供了对象和表之间进行映射的框架,使得这种转换更加方便. 1.ORM概念 ...

  3. 对项目的测试--Resharper

    初学 这里做个记录. 1:安装后,Resharper会用他自己的英文智能提示,替换掉 vs2010的智能提示,所以我们要换回到vs2010的智能提示 2:快捷键.是使用vs2010的快捷键还是使用 R ...

  4. Mac运行exe的几种方法,欢迎补充!

    1. 用wine直接运行exe.安装wine后有个放exe的文件夹,双击后会自动包装运行.看起来挺方便的,就怕暂用资源比较大: http://www.youtube.com/watch?v=eYISV ...

  5. hadoop版本和位数的查看方法

    目前针对apache hadoop更新的版本较多,由此而产生了两个方面的问题: 1.如何查看运行的集群当中的hadoop的版本的问题. 2.如何查看运行集群当中的hadoop的位数 下面详细的介绍一下 ...

  6. PAT 06-3 单词长度

    此题为简化版,题设为“以'.'结尾”.“单词与语言无关”.三种情况下的输入输出为 . -> 无输出 a     b. ->1 1(无空格) a   b  . ->1 1(无空格) 程 ...

  7. Python闭包实现的计数器

    #!/usr/bin/env python #coding=utf-8 def generate_counter(): CNT = [0] def add_one(): CNT[0] = CNT[0] ...

  8. 用Ogre实现《天龙八部》场景中水面(TerrainLiquid)详解

    本文主要讲的是<天龙八部>游戏中水面(TerrainLiquid)的具体实现,使用C++,Ogre1.6. 天龙的水面做的比较简单,虽然没有倒影,但动态纹理+深度图做出的效果还行,看着不是 ...

  9. php大力力 [026节] php开发状态要随时做好整理工作

    php大力力 [026节]  php开发状态要随时做好整理工作: 1.整理了开发目录,以及文件命名: 2.做了各个页面的快捷方式: 3.把浏览器safari的很多没来得及消化的页面链接,写入了我的在线 ...

  10. C++面向对象编程解决三阶矩阵相加减

    /*此处用面向对象编程*/ #include<iostream> #include<string.h> using namespace std; class Matrices ...