您的位置:首页 > 编程语言 > C语言/C++

C++文本查询程序实例

2015-08-03 15:37 218 查看

需求介绍

假如有这样的需求:

处理一个英文文本(简单处理为无标点),用户输入一个单词:如you,

程序执行,显示you在文本文件中出现的次数,以及其所在行的内容。如果该单词在一行中出现多次,则此行只显示一次即可。查询结果按行号升序输出各行内容。

解决思路

利用C++实现这样一个简单的文本查询需求十分简单。

编写两个类

1)TextQuery

2)QueryResult

所用数据结构:

使用vector< string > 保存文本文件

用istringstream将每行分解为单词

使用set来保存单词在文本中出现的所有行号

使用map将每个单词与其出现所有行号的set进行映射

使用shared_ptr 进行对象内存共享

具体实现代码:

类定义 & 成员函数

最好分开文件实现(在此偷懒都写在一个头文件中)

#ifndef _TEXTQUERY_H
#define _TEXTQUERY_H

#include <string>
using std::string;

#include <vector>
using std::vector;

#include <map>
#include <set>

#include <memory>
using std::shared_ptr;

#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>

using namespace std;

class QueryResult;

class TextQuery {
public:
using line_no = std::vector<std::string>::size_type;

TextQuery(ifstream &input_file);
QueryResult query(const string &input_word) const;

private:
//输入文件,用vector<string>逐行保存 ,shared_ptr共享一份内存
shared_ptr<vector<string>> file;

//每个单词到其所在行号的集合的映射
map<string,shared_ptr<set<line_no>>> word_map;
};

//构造函数
TextQuery::TextQuery(ifstream &input_file):file(new vector<string>) {
string line_content;
while (getline(input_file,line_content)) {
file->push_back(line_content);   //保存文本每行
int number = file->size()-1;   //获取行号

//分解为单词
istringstream line(line_content);
string word;

while (line >> word) {
auto &lines = word_map[word];  //获取单词对应的行号set(shared_ptr共享的行号集合)
if (!lines)
lines.reset(new set<line_no>); //新单词,分配一个新的行号set

lines->insert(number); //将该行号插入set中
}
}
}

//**************************************************
//查询结果类
class QueryResult {
using line_no = std::vector<std::string>::size_type;

public:
friend ostream& showAnswer(ostream& os,const QueryResult&);  //显示查询结果

//查询结果构造函数
QueryResult(string w, shared_ptr<set<line_no>> l,shared_ptr<vector<string>> f)
:input_word(w),lines(l),file(f){}

private:
string input_word;              //查询的单词
shared_ptr<set<line_no>> lines;  //出现的行号
shared_ptr<vector<string>> file;  //处理的文件
};

QueryResult TextQuery::query(const string &input_word) const {
//查无此词
static shared_ptr<set<line_no>> notinfile(new set<line_no>);

auto location = word_map.find(input_word);
if (location == word_map.end()) {
return QueryResult(input_word,notinfile,file);
} else {
return QueryResult(input_word,location->second,file);  //second指集合
}
}

ostream& showAnswer(ostream &os, const QueryResult &qr) {
//找到单词,输出出现次数,所有出现位置
os << qr.input_word << "出现:" << qr.lines->size() << " "<< "次" << endl;

for(auto num : *qr.lines) {
os << "\t(line " << num +1 << ")" << *(qr.file->begin()+num ) << endl;
}

return os;
}

#endif


测试函数:

/*************************************************************************
> File Name: main_test.cpp
> Author:
> Mail:
> Created Time: Fri 31 Jul 2015 08:39:45 AM PDT
************************************************************************/

#include<iostream>
#include "TextQuery.h"

using namespace std;

void runQueries(ifstream &input_file) {
TextQuery text_query(input_file);

while(true) {
cout << "请输入要查询的单词(按q退出):" << endl;
string input_word;

if (!(cin >> input_word) || input_word == "q") break;

showAnswer(cout,text_query.query(input_word)) << endl;
}
}

int main(void) {

ifstream file("test.txt");
runQueries(file);

return 0;
}


测试文本:

hello allen  how are you i am fine thank you.
hello fay how old are you you are so cute
hi jay i am your big fans.
good job well done
and you
thank you


运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: