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
运行结果:
相关文章推荐
- 06-2. 字符串字母大小写转换(10)
- C++对象的动态建立与释放详解
- C语言中一个小问题
- C语言深度解剖——读书笔记-10、指针和数组
- hnuoj 字典树 map c++
- (转)c++迭代器
- C++ const关键字的总结
- c++ 覆盖、重载、隐藏
- C++中拷贝构造函数
- C语言:堆结构串(动态分配内存)
- C++构造函数和拷贝构造函数详解
- C语言写CGI 程序简要指南
- [LeetCode] Valid Anagram
- C语言-全局变量和局部变量
- 一种新排序算法的探讨
- c++中sizeof的分析
- C++中类定义的细节
- CString的成员函数
- c++ 整型最大值与最小值
- C语言中volatile关键字的作用