C++ demo:文本搜索以及'指针的引用'的思考

xiaoxiao2021-02-28  109

功能:

本程序允许用户在一个给定的文件中查询单词。查询结果是单词在文件中出现的次数及其所在行的列表。如果一个单词在一行中出现多次,此行只列出一次。行会按照升序输出,即第7行会在第9行之前显示。

思路:

使用vector来保存整个输入文件的一份拷贝。输入文件中每一行保存为vector中的元素。当需要打印一行时,可以用行号作为下标来提取行文本。使用istringstream来将每行分解为单词。使用set来保存每个单词输入文本中出现的行号(有序的set)使用map来将每个单词与它出现的行号set关联起来,这样就可以快速提取任意单词的set。

源码:

TextQuery.h文件

// // Created by liangyh on 7/9/2017. // #ifndef SECOND_TEXTQUERY_H #define SECOND_TEXTQUERY_H #include <vector> #include <map> #include <set> #include "QueryResult.h" using namespace std; class TextQuery { public: using line_no = vector<string>::size_type; TextQuery(ifstream &inFile); QueryResult query(string &sought); private: shared_ptr<vector<string>> file; map<string, shared_ptr<set<line_no>>> wordMap; }; #endif //SECOND_TEXTQUERY_H

TextQuery.cpp文件

#include <fstream> #include <sstream> #include "TextQuery.h" //构造:file文件对象和wordMap对象。 TextQuery::TextQuery(ifstream &inFile) :file(new vector<string>) { string line; while (getline(inFile, line)) { file->push_back(line); istringstream words(line); string word; while (words >> word) { shared_ptr<set<line_no >> &lines = wordMap[word]; if (!lines) { lines.reset(new set<line_no >); //wordMap[word] = lines;//开始的时候wordMap中的value值是NULL的。 } lines -> insert(file->size() - 1); } } } QueryResult TextQuery::query(string &sought) { static shared_ptr<set<line_no >> noData(new set<line_no >); auto pair = wordMap.find(sought); if (pair == wordMap.end()) {//not found return QueryResult(sought, noData, file); } else { return QueryResult(sought, pair->second, file); } }

QueryResult.h文件

// // Created by liangyh on 7/9/2017. // #ifndef SECOND_QUERYRESULT_H #define SECOND_QUERYRESULT_H #include <vector> #include <set> #include <map> #include <memory> using namespace std; class QueryResult { public: using line_no = vector<string>::size_type; QueryResult(string sought, shared_ptr<set<line_no >> numSet, shared_ptr<vector<string>> file); void print(); private: string sought; shared_ptr<vector<string>> file; shared_ptr<set<line_no>> numSet; }; #endif //SECOND_QUERYRESULT_H

QueryResult.cpp文件

// // Created by liangyh on 7/9/2017. // #include <iostream> #include <string> #include "QueryResult.h" QueryResult::QueryResult(string sought, shared_ptr<set<line_no >> numSet, shared_ptr<vector<string>> file) : sought(sought), numSet(numSet), file(file) { } void QueryResult::print() { cout << "sought word is: " << sought << endl; if (numSet->size() > 0) { for (auto num : *numSet) { cout << *(file->begin() + num) << endl; cout << "-----" << endl; } } else { cout << sought << ": ------------0------------" << endl; } }

main函数

#include <iostream> #include <fstream> #include <string> #include "TextQuery.h" #include "QueryResult.h" using namespace std; int main() { string filePath = "C:\\Users\\liangyh\\Desktop\\TEMP\\query.txt"; ifstream file(filePath.c_str()); if (file.is_open()) { TextQuery textQuery(file); string soughtWord = "is"; QueryResult result = textQuery.query(soughtWord); result.print(); } system("pause"); return 0; }

思考:指针的引用

下面是构造函数的代码

//构造:file文件对象和wordMap对象。 TextQuery::TextQuery(ifstream &inFile) :file(new vector<string>) { string line; while (getline(inFile, line)) { file->push_back(line); istringstream words(line); string word; while (words >> word) { shared_ptr<set<line_no >> &lines = wordMap[word]; if (!lines) { lines.reset(new set<line_no >); //wordMap[word] = lines;//开始的时候wordMap中的value值是NULL的。 } lines -> insert(file->size() - 1); } } }

该构造方法中使用到了指针的引用,该行代码为:

shared_ptr<set<line_no >> &lines = wordMap[word];

lines是一个指针,修改lines的内容就会修改它所指向的内容;同时,lines又是引用,因此,(*lines)就代表了lines所指向的内容本身:一开始的时候,wordMap[word]是null的,所以(*line)也是null的,当执行完下面两行代码之后,*lines就不再为null了。又因为lines是wordMap[word]的引用,因此wordMap[word]也不为null了。

lines.reset(new set<line_no >); lines -> insert(file->size() - 1);

如果不使用指针的引用,需要怎么修改呢?先贴出代码

shared_ptr<set<line_no >> lines = wordMap[word]; if (!lines) { lines.reset(new set<line_no >); wordMap[word] = lines; } lines -> insert(file->size() - 1);

开始的时候wordMap[word]是null的,在初始化lines变量的时候并不能让lines指向一个有效的地址,也就是开始的时候lines是空指针。它跟lines没有关联,即使执行了lines.reset(new set<line_no >);,wordMap[word]还是为null。因此,需要我们把他们关联起来,即wordMap[word] = lines;。 所有,把代码改成如下所示的样子也是可以的。

while (words >> word) { shared_ptr<set<line_no>> tmpLines(new set<line_no>); wordMap.insert(pair<string, shared_ptr<set<line_no>>>(word, tmpLines)); shared_ptr<set<line_no >> lines = wordMap[word]; if (!lines) { lines.reset(new set<line_no >); //wordMap[word] = lines; } lines->insert(file->size() - 1); }

对于指针的引用,有一个demo,p是指针的引用,因此,p代表了temp变量,*p改变的时候,temp也会改变。

void test() { int a = 1; int *temp = &a; int *&p = temp; cout << "*p = " << *p << endl; cout << "temp = " << *temp << endl; *p = 5; cout << "*p = " << *p << endl; cout << "temp = " << *temp << endl; int b = 2; p = &b; cout << "*p = " << *p << endl; cout << "temp = " << *temp << endl; }

执行的结果是:

*p = 1 temp = 1 *p = 5 temp = 5 *p = 2 temp = 2 Press any key to continue . . .

结束!

转载请注明原文地址: https://www.6miu.com/read-83986.html

最新回复(0)