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