c++学习笔记:文本查询程序

来源:互联网 发布:考研有多难放弃知乎 编辑:程序博客网 时间:2024/06/07 03:22

文本查询程序:

在给定的文件中查询一个单词出现的次数及其所在行的列表,如果单词在一行中出现多次,那这一行的文本只列出一次

1)使用一个vector<string>来保存文件的一份拷贝,文件的每一行作为vector对象的一个元素。当要打印一行时,使用下标来提取一行的文本。

2)使用istringstream来把每一行分解成一个个单词

3)使用set来保存每个单词在文本中出现的行号,保证行号只出现一次

4)使用map来将每个单词和它出现的行号set关联在一起



一。建立映射关系

1)BuildMap函数接受两个参数,一个是文件输入流,一个是vector对象,两个都是传引用。因为流不能拷贝,所以只能要传引用。而vector传引用是直接存入在主函数中定义的vector对象,这个对象保存的是文件的一份副本。

2)函数先用getline函数循环读取文件的每一行,然后存入传进来的vector对象当中,vector对象的size作为行号

3)然后使用istringstream将每一行文本分解成一个个单词,每个单词作为map对象的关键字。然后将行号存入map对象的值中。map对象的值是一个set,保证保存的行号无重复。所以即使一行中出现多个重复的单词,也只保存一个行号。

std::map<std::string, std::set<line_no_type>> BuildMap(std::ifstream &input_stream, std::vector<std::string> &file){std::string word;std::string text;std::map<std::string, std::set<line_no_type>> word_map;while (getline(input_stream, text)) {file.push_back(text);auto line_no = file.size();std::istringstream line(text);     while (line >> word) {auto &set_no = word_map[word]; //注意是引用,这样才能将元素添加到原set中去set_no.insert(line_no);}}return word_map;}


二、查询

1)输入要查找的单词,然后用关联容器的find()查找。如果给定的单词在容器中找到,就返回一个指向关键字为给定单词的元素的迭代器,否则返回尾后迭代器。因为容器是map,所以返回一个指向pair的迭代器。

2)如果找到,则set的元素个数就是单词出现的次数。然后从set提取单词所在的行号,用这个行号作为vector的下标去提取vector对象中的文本。(行号减去1才是正确的下标)

void RunQuery(const std::map<std::string, std::set<line_no_type>> &word_map, const std::vector<std::string> &file){std::string word;while (true) {std::cout << "输入你要查询的单词(q 退出): ";std::cin >> word;if (word == "q")break;auto iter = word_map.find(word); //返回一个指向pair的迭代器if (iter != word_map.end()) {std::cout << "单词 " << word << " 出现 " << iter->second.size() << " 次" << std::endl;for (auto index : iter->second)std::cout << "\t(第 " << index << " 行)" << file[index - 1] << std::endl; //提取文本的时候要将index - 1}elsestd::cout << "单词 " << word << " 出现 0 次"<< std::endl;}}


程序全部源码:

#include <iostream>#include <sstream>#include <fstream>#include <cstdlib>#include <string>#include <vector>#include <map>#include <set>using line_no_type = std::vector<std::string>::size_type;std::map<std::string, std::set<line_no_type>> BuildMap(std::ifstream &input_stream, std::vector<std::string> &file);void RunQuery(const std::map<std::string, std::set<line_no_type>> &word_map, const std::vector<std::string> &file);int main(int argc, char **argv){if (argc != 2) {std::cout << "缺少参数" << std::endl;exit(EXIT_FAILURE);}std::vector<std::string> file;std::ifstream input_stream(argv[1]);auto word_map = BuildMap(input_stream, file);RunQuery(word_map, file);return 0;}void RunQuery(const std::map<std::string, std::set<line_no_type>> &word_map, const std::vector<std::string> &file){std::string word;while (true) {std::cout << "输入你要查询的单词(q 退出): ";std::cin >> word;if (word == "q")break;auto iter = word_map.find(word); //返回一个指向pair的迭代器if (iter != word_map.end()) {std::cout << "单词 " << word << " 出现 " << iter->second.size() << " 次" << std::endl;for (auto index : iter->second)std::cout << "\t(第 " << index << " 行)" << file[index - 1] << std::endl; //提取文本的时候要将index - 1}elsestd::cout << "单词 " << word << " 出现 0 次"<< std::endl;}}std::map<std::string, std::set<line_no_type>> BuildMap(std::ifstream &input_stream, std::vector<std::string> &file){std::string word;std::string text;std::map<std::string, std::set<line_no_type>> word_map;while (getline(input_stream, text)) {file.push_back(text);auto line_no = file.size();std::istringstream line(text);     while (line >> word) {auto &set_no = word_map[word]; //注意是引用,这样才能将元素添加到原set中去set_no.insert(line_no);}}return word_map;}



原创粉丝点击