文本查询程序(动态内存的使用)

本文介绍了一个使用C++实现的文本查询程序,该程序能够读取文件内容并提供高效的单词查询功能。通过构建文本查询类`TextQuery`和查询结果类`QueryResult`,可以快速查找指定单词出现的所有行及其上下文。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

来源:C++ Primer(中文版)(第5版)(第12章)

1、头文件

#ifndef query_h__
#define query_h__

/*
文本查询程序
*/

#include <vector>
#include <set>
#include <map>
#include <memory>
#include <string>
#include <fstream>
#include <iostream>

using std::vector;
using std::map;
using std::set;
using std::shared_ptr;
using std::string; 
using std::ifstream;
using std::ostream;

//前置声明
class QueryResult;

//文本查询类
class TextQuery
{
public:
	using line_no = vector<string>::size_type;//行号类型
	TextQuery(ifstream&);//通过文件流构造
	QueryResult query(const string &)const;//查询某个单词的结果

private:
	//对于一个文件,容器存储所有行文本
	shared_ptr<vector<string>> m_file;
	//每个单词映射到它所在的行号的集合
	map<string, shared_ptr<set<line_no>>> m_wm;
};

//查询结果类
class QueryResult
{
	//打印查询结果,仅声明它是友元,并没有声明这个函数
	friend ostream & print(ostream&, const QueryResult&);
	using line_no = TextQuery::line_no;

public:
	QueryResult(const string &s,
		shared_ptr<set<line_no>>p,
		shared_ptr<vector<string>> f)
		: m_sought(s), m_lines(p), m_file(f)
	{}

private:
	string m_sought;//查询的单词
	shared_ptr<set<line_no>> m_lines;//这个单词出现的行号的集合
	shared_ptr<vector<string>> m_file;//在哪个文件中查询这个单词
};

//函数声明  打印查询结果
ostream & print(ostream&, const QueryResult&);

#endif // query_h__

2、源文件

#include "query.h"
#include <sstream>

using std::istringstream;
using std::endl;

TextQuery::TextQuery(ifstream &is)
	: m_file(new vector<string>)//分配文件内存
{
	string line;//行文本
	while (getline(is,line))//获取文件中每一行
	{
		m_file->push_back(line);//保存
		line_no n = m_file->size() - 1;//当前行号		
		istringstream sin(line);
		string word;
		while (sin >> word)//获取这一行的每个单词
		{
			/*
			如果单词不在m_wm中,则会作为下标添加到m_wm中,
			此时指针会为空
			*/
			auto &lines = m_wm[word];//shared_ptr<set<line_no>>的引用
			if (!lines)//空指针
			{
				lines.reset(new set<line_no>);//分配内存
			}
			lines->insert(n);//添加行号
		}
	}
}

QueryResult TextQuery::query(const string &sought) const
{
	auto loc = m_wm.find(sought);//查询单词
	if (loc == m_wm.end())//没查询到
	{
		static shared_ptr<set<line_no>> nodata(new set<line_no>);
		return QueryResult(sought, nodata, m_file);
	} 
	else
	{
		return QueryResult(sought, loc->second, m_file);
	}
}

ostream & print(ostream &os, const QueryResult&qr)
{
	os << qr.m_sought << " occurs " << qr.m_lines->size() 
		<< " time(s)" << endl;

	//*qr.m_lines:set<line_no>
	for (auto num : *qr.m_lines)
	{
		os << "\t(line " << num + 1 << ") "
			/*
			qr.m_file : shared_ptr<vector<string>>
			qr.m_file->begin() : 第一个vector<string>::iterator
			qr.m_file->begin() + num : 第num个vector<string>::iterator
			*(qr.m_file->begin() + num) : 解引用这个迭代器
			*/
			<< *(qr.m_file->begin() + num) << endl;
	}
	return os;
}

3、实现文件

#include "query.h"

using std::cin;
using std::cout;
using std::endl;

int main()
{
	ifstream fin("file.txt");
	if (!fin)//打开文件失败
	{
		return EXIT_FAILURE;
	}
	
	TextQuery tq(fin);//文本查询

	fin.close();//关闭文件

	while (true)
	{
		cout << "enter word to look for, or q to quit: ";
		string s;
		if (!(cin >> s) || s == "q")//输入失败,或输入q,则退出
		{
			break;
		}
		print(cout , tq.query(s)) //打印查询结果
			<< endl;
	}

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值