IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++ Primer 第十二章 文本查询程序:TextQuery类,QueryResult类 -> 正文阅读

[C++知识库]C++ Primer 第十二章 文本查询程序:TextQuery类,QueryResult类

#include<iostream>
#include<map>
#include<set>
#include<string>
#include<cstring>
#include<cstdlib>
#include<fstream>
#include<sstream>
using namespace std;
class QueryResult;

class TextQuery
{
public:
	using line_no = vector<string>::size_type;  // vector<string> 里面的下标都用line_no代替
	TextQuery(ifstream&);  // 构造函数
	QueryResult query(const string& s)const;    //查询一个单词是否存在的成员函数
private:
	shared_ptr<vector<string>> file;			// 指向一个动态开辟的vector<string>
	map<string, shared_ptr<set<line_no>>> wm;   // 一个map,first是string,second是智能指针指向一个set<int>
};

TextQuery::TextQuery(ifstream& is):file(new vector<string>())  // 构造函数
{
	// 作用就是给这个TextQuery类的对象初始化,这是一个构造函数嘛,把成员file以及wm初始化
	string text;
	while (getline(is, text))
	{
		file->push_back(text);     // 将文件中的每一行存入vector<string>中
		int n = file->size() - 1;  // 存入的这一行的行号
		istringstream line(text);  // 看不懂
		string word;
		while (line >> word)       // 一行中的每个单词
		{
			auto& lines = wm[word];// lines是一个shared_ptr 
			if (!lines)            // 在我们第一次遇到这个单词时,此指针为空
				lines.reset(new set<line_no>); // 分配一个新的set
			lines->insert(n);      // 将此行号插入set中
		}
	}
}

QueryResult TextQuery::query(const string& sought)const
{
	// 如果未找到sought,我们将返回一个指向此set的指针
	static shared_ptr<set<line_no>> nodata(new set<line_no>);
	// 使用find而不是下标运算符来查找单词,避免将单词添加到wm中
	auto loc = wm.find(sought);   //loc是一个迭代器,指向那对元素,first是一个string,second是一个智能指针,指向一个set<line_no>
	if (loc == wm.end())
	{
		return QueryResult(sought, nodata, file);  // 此处file是一个智能指针,传递的时候就非常方便了
	}
	else
	{
		return QueryResult(sought, (*loc).second, file);  // 这里返回的第二个参数就是一个shared_prt<set<line_no>>类型的对象
	}
}

class QueryResult //查询结果的类,只是用来保存这个文件,查询的单词,以及这个单词所匹配的set,那个TextQuery类中的map并没有传递,只是传了map的second:shared_ptr<set<line_no>>
{
	friend ostream& print(ostream&, const QueryResult&);
public:
	QueryResult(string s, shared_ptr<set<TextQuery::line_no>> p, shared_ptr<vector<string>> f)
		:sought(s), lines(p), file(f) {}
private:
	string sought;  // 查询的单词
	shared_ptr<set<TextQuery::line_no>> lines;  // 指向出现的行号所集成的set的智能指针
	shared_ptr<vector<string>> file;            // 输入文件,此处用的是智能指针,不会造成复制等耗费时间的事情
};


ostream& print(ostream& os, const QueryResult& qr)  // qr保存的是那个单词,以及指向保存文本文件的vector<string>的指针
{
	os << qr.sought << " occurs " << (*(qr.lines)).size() << " times" << endl;  // 后面那个是set的size()
	for (const auto& num : *(qr.lines))
	{
		os << "\t(lines " << num + 1 << ") " << (*(qr.file))[num]/**(qr.file->begin() + num)*/ << endl;
	}
	return os;
}

void runQueries(ifstream &infile)
{
	// infile是一个ifstream,指向我们要处理的文件
	TextQuery tq(infile);   // 保存文件并建立查询map
	// 与用户交互,提示用户输入要查询的单词,完成查询并打印结果
	while (true)
	{
		string word;
		cout << "enter word to look for, or q to quit";
		// 若遇到文件尾或用户输入了'q'时循环终止
		if (!(cin >> word) || word == "q")
			break;
		// 指向查询并打印结果
		// 每输入一个单词,就调用这个保存好输入的文件的TextQuery类的对象的成员函数query去查询这个单词,返回值是一个QueryResult类的对象
		print(cout, tq.query(word)) << endl;
	}
}

略去了主函数,由于第八章没学好,所以有关文件的读取,以及其中神奇的sstringstream也没能理解。这个程序对于理解智能指针shared_ptr<>类以及map,set类,以及没有掌握的文件读取都是一个很好的练习和巩固。

其实程序的一些细节算法并不难,主要是怎么选择合适的数据结构来处理这个文本文件,这两个类的结合,TextQuery类只有一个构造函数,参数是ifstream&,这个类的作用就是把这个文件里的文本处理之后,存储在shared_ptr<vector<string>>智能指针以及map<string, shared_ptr<set<size_type>>>中,这个map存储每个单词出现的行号,每个string对应一个shared_ptr<set<size_type>>智能指针,而唯一的实用查询成员函数,query就是来接收一个string,然后返回一个合适的智能指针,如果这个string(单词)存在,则返回map中string配对的那个智能指针,指向set保存行号,如果不存在,返回的智能指针即函数内创建的指向空set的智能指针,而这些shared_ptr并不是直接返回的,而是把这个shared_ptr和单词,以及文本封装在一个QueryResult类的对象中,这个对象就是它的名字所说的:查询结果。即查询的单词,以及查询的文本,以及查询结果,这个结果就是一个指向一个set的shared_ptr,保存的是查询的文本中单词出现的行号,这里用shared_ptr就避免了拷贝set和vector所带来的性能损耗。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-18 17:26:01  更:2022-05-18 17:27:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/10 14:47:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码