C++ Primer : 第十二章 : 文本查询程序
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 : 第十二章 : 文本查询程序的更多相关文章
- 【WPF学习】第二十二章 文本控件
		
WPF提供了三个用于输入文本的控件:TextBox.RichTextBox和PasswordBox.PasswordBox控件直接继承自Control类.TextBox和RichTextBox控件间接 ...
 - C++ Primer : 第十二章 : 动态内存之unique_ptr和weak_ptr
		
unique_ptr 一个unique_ptr拥有它所管理的对象,与shared_ptr不同,unique_ptr指向的对象只能有一个用户.当unique_ptr被销毁后,它所指向的对象也被销毁. 定 ...
 - C++Primer 第十二章
		
//1.标准库提供了两种智能指针类型来管理动态对象,均定义在头文件memory中,声明在std命名空间. // shared_ptr:允许多个指针指向同一个对象. // unique_ptr:独占所指 ...
 - C++ Primer : 第十二章 : 动态内存之allocator类
		
标准库allocator类定义在头文件 <memory>中.它帮助我们将内存分配和构造分离开来,它分配的内存是原始的.未构造的. 类似vector,allocator也是一个模板类,我们在 ...
 - C++ Primer : 第十二章 : 动态内存之动态数组
		
动态数组的分配和释放 new和数组 C++语言和标准库提供了一次分配一个对象数组的方法,定义了另一种new表达式语法.我们需要在类型名后跟一对方括号,在其中指明要分配的对象的数目. int* arr ...
 - C++ Primer : 第十二章 : 动态内存之shared_ptr与new的结合使用、智能指针异常
		
shared_ptr和new结合使用 一个shared_ptr默认初始化为一个空指针.我们也可以使用new返回的指针来初始化一个shared_ptr: shared_ptr<double> ...
 - C++ Primer : 第十二章 : 动态内存之动态内存管理(new和delete)
		
C++语言定义了两个运算符来分配和释放动态内存:运算符new分配内存,运算符delete释放new分配的内存. 运算符new和delete 使用new动态分配和初始化对象 在自由空间分配的内存是无名的 ...
 - C++ Primer : 第十二章 : 动态内存之shared_ptr类实例:StrBlob类
		
StrBlob是一个管理string的类,借助标准库容器vector,以及动态内存管理类shared_ptr,我们将vector保存在动态内存里,这样就能在多个对象之间共享内存. 定义StrBlob类 ...
 - C++ Primer : 第十二章 : 动态内存之shared_ptr类
		
在C++中,动态内存是的管理是通过一对运算符来完成的:new ,在动态内存中为对象分配空间并返回一个指向该对象的指针,delete接受一个动态对象的指针,销毁该对象,并释放该对象关联的内存. 动态内 ...
 
随机推荐
- Jmeter简单测试elasticsearch服务器
			
入门知识: Jmeter是一个非常好用的压力测试工具. Jmeter用来做轻量级的压力测试,非常合适,只需要十几分钟,就能把压力测试需要的脚本写好. 顾名思义:压力测试,就是 被测试的系统,在一定 ...
 - android自定义控件实例(Linearlayout组合TextView和ImageView)
			
2013-12-18 11:25:22 转载自: http://www.open-open.com/lib/view/open1328836804515.html 很多时候android常用的控件不能 ...
 - [vijos P1112] 小胖的奇偶
			
第一次看到这题怎么也不会想到是并查集题目…星期五第一次看到这题,到今天做出来,实在是废了好多功夫.看了很多人的解题都有same和diff数组,我也写了,后来发现不对啊两个数组的话find函数怎么写呢? ...
 - SOD 精选细节--常用工具
			
要明白一个思想: SOD 只是帮你拼接sql语句, 用简单的方式来帮你实现. 不要理解错了.这很重要的! 查询: TB table=new TB(); table.Name="111& ...
 - Android TextView多行垂直滚动
			
在Android应用中,有时候需要TextView可以垂直滚动,今天我就介绍一下怎么实现的.在布局里: <TextView android:id="@+id/tvCWJ" a ...
 - java基础-005
			
27.Java中垃圾回收的目的及回收的时机 垃圾回收的目的是识别并且丢弃不再使用的对象来释放和重用资源. 如果对象的引用被置为null,垃圾收集器不会立即释放对象占用的内存. 什么时候进行垃圾回收,主 ...
 - Notification通知栏
			
Notification通知栏 首先实现的功能就是通知栏显示Notification,Notification是显示在系统的通知栏上面的,所以Notification 是属于进程之前的通讯.进程之间的 ...
 - bistu新生-1004
			
#include "stdio.h"#include "stdlib.h"#include "math.h"int cmp(const vo ...
 - 迪士尼黑科技:爬墙机器人 VertiGo
			
12 月 30 日,迪士尼研发出的一款爬墙机器人曝光了一段有趣的视频.从视频里可看出这个机器人碰到墙壁时迅速地作出反应爬了上去. 据了解,这个爬墙机器人名叫 VertiGo,由迪士尼研究中心和苏黎世联 ...
 - 设置vs2008代码区的背景色
			
编写程序.调试代码时,是不是感觉文字的白色背景有些刺眼呢?vs2008 给我们提供了改变背景色的功能. 依次展开:工具->选项->环境->字体和颜色,在“显示项--纯文本--项背景色 ...