標准庫,智能指針,綜合運用的小例子
功能說明:查詢單詞在文件中出現的次數,如果在同一行出現多次,只算一次。
比如查詢單詞:你好
輸出的結果:
你好 出現了:2次
(行號 2)xxxxxxx 你好
(行號 3)bbb ccc 你好 xxxxx
注意點:代碼的46行,必須使用引用。
//非常重要,必須用引用,要不然就會拷貝一個新的set給lines,不是map里的set
auto &lines = wm[word];//lines是shared_ptr
代碼:
#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <memory>
using namespace std;
class QueryResult{
friend ostream& print(ostream&, const QueryResult&);
public:
using line_no = vector<string>::size_type;
QueryResult(string s, shared_ptr<set<line_no>> p,
shared_ptr<vector<string>> f):
sought(s), lines(p), file(f){}
private:
string sought;//查詢的單詞
shared_ptr<set<line_no>> lines;//出現的行號
shared_ptr<vector<string>> file;
};
//QueryResult的友元函數
ostream& print(ostream& os, const QueryResult& qr){
os << qr.sought << " 出現了:" << qr.lines->size() << "次" << endl;
for(auto num : *qr.lines){
os << "\t(行號 " << num + 1 << ")"
<< *(qr.file->cbegin() + num) << endl;
}
return os;
}
class TextQuery{
public:
using line_no = vector<string>::size_type;
TextQuery(ifstream& is) : file(new vector<string>){
string text;
while(getline(is, text)){//讀文件的每一行
file->push_back(text);
int n = file->size() - 1;//當前行號
istringstream line(text);//將行文本分解為單詞
string word;
while(line >> word){
//非常重要,必須用引用,要不然就會拷貝一個新的set給lines,不是原來的
auto &lines = wm[word];//lines是shared_ptr
if(!lines)
lines.reset(new set<line_no>);
lines->insert(n);
}
}
}
QueryResult query(const string &sought) const{
//如果沒有找到sought,返回指向此set的一個智能指針
static shared_ptr<set<line_no>> nodata(new set<line_no>);
auto ret = wm.find(sought);
if(ret == wm.end()){
return QueryResult(sought, nodata, file);//沒有找到
}
else{
return QueryResult(sought, ret->second, file);
}
}
private:
shared_ptr<vector<string>> file;
map<string, shared_ptr<set<line_no>>> wm;
};
int main(){
ifstream infile("/home/ys/c++_template/search_text");
TextQuery tq(infile);
while(true){
cout << "輸入要查找的單詞: q 退出";
string s;
if(!(cin >> s) || s == "q")break;
print(cout, tq.query(s)) << endl;;
}
}