《C++ Premier》第5版 第12章 动态内存(智能指针) 讲解了
shared_ptr
weak_ptr
unique_ptr
但是没有讲解多线程情况下(在公司中)如何安全的使用智能指针
进阶学习,参看《C++标准库 第2版》侯捷译 5.2 Smart Pointer(智能指针) P76
12.3 使用标准库:文本查询程序
这个程序特别棒,可以初窥面向对象编程思想 ,可以看到如何通过代码展现面向对象编程
querymain.cpp
#include <string>
using std::string;
#include <fstream>
using std::ifstream;
#include <iostream>
using std::cerr;
using std::cin;
using std::cout;
using std::endl;
#include <cstdlib>
#include "TextQuery.h"
void runQueries(ifstream &infile)
{
TextQuery tq(infile);
while (true)
{
cout << "enter word to look for, or q to quit: ";
string s;
if (!(cin >> s) || s == "q")
break;
print(cout, tq.query(s)) << endl;
}
}
int main(int argc, char **argv)
{
ifstream infile;
if (argc < 2 || !(infile.open(argv[1]), infile))
{
cerr << "No input file!" << endl;
return EXIT_FAILURE;
}
runQueries(infile);
return 0;
}
TextQuery.h
#ifndef TEXTQUERY_H
#define TEXTQUERY_H
#include <memory>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <fstream>
#include "QueryResult.h"
using std::ifstream;
using std::map;
using std::set;
using std::shared_ptr;
using std::string;
using std::vector;
inline string make_plural(size_t ctr,
const string &word,
const string &ending)
{
return (ctr > 1) ? word + ending : word;
}
class QueryResult;
class TextQuery
{
public:
typedef size_t line_no;
public:
TextQuery(ifstream &);
QueryResult query(const string &) const;
void display_map(); //请勿随便调用,因为数据量大 会把终端卡崩溃
private:
shared_ptr<vector<string>> file;
map<string, shared_ptr<set<line_no>>> wm;
static string cleanup_str(const string &);
};
#endif
TextQuery.cpp
#include "TextQuery.h"
#include "QueryResult.h"
#include <cstddef>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <iostream>
#include <fstream>
#include <cctype>
#include <cstring>
#include <utility>
using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::getline;
using std::ifstream;
using std::ispunct;
using std::istringstream;
using std::map;
using std::ostream;
using std::pair;
using std::set;
using std::shared_ptr;
using std::size_t;
using std::string;
using std::strlen;
using std::tolower;
using std::vector;
/**
* 构造函数
* 读取文件内存,存入file所指向的vector<string>>
* 针对每一行中的,每个单词,存到map中
* 每个单词对应于map中的一项,first是单词本身,second是单词所在行的set集合
*/
TextQuery::TextQuery(ifstream &is) : file(new vector<string>)
{
string text;
while (getline(is, text))
{
file->push_back(text);
int n = file->size() - 1; //行当前的下标(从0开始)
istringstream line(text);
string word;
while (line >> word)
{
word = cleanup_str(word);
shared_ptr<set<line_no>> &lines = wm[word];
if (!lines)
lines.reset(new set<line_no>);
lines->insert(n);
}
}
}
/**
* 是标点符号,则去除
* 不是标点符号,则全部转换为小写字母;这样就不对大小写敏感了
*/
string TextQuery::cleanup_str(const string &word)
{
string ret;
for (string::const_iterator it = word.begin(); it != word.end(); ++it)
{
if (!ispunct(*it))
ret += tolower(*it);
}
return ret;
}
QueryResult TextQuery::query(const string &sought) const
{
static shared_ptr<set<line_no>> nodata(new set<line_no>);
auto loc = wm.find(cleanup_str(sought));
if (loc == wm.end())
return QueryResult(sought, nodata, file);
else
return QueryResult(sought, loc->second, file);
}
ostream &print(ostream &os, const QueryResult &qr)
{
os << qr.sought << " occurs " << qr.lines->size() << " "
<< make_plural(qr.lines->size(), "time", "s") << endl;
for (QueryResult::line_no num : *qr.lines)
os << "\t(line " << num + 1 << ") "
<< *(qr.file->begin() + num) << endl;
return os;
}
void TextQuery::display_map()
{
map<string, shared_ptr<set<line_no>>>::iterator iter = wm.begin();
map<string, shared_ptr<set<line_no>>>::iterator iter_end = wm.end();
for (; iter != iter_end; ++iter)
{
cout << "word: " << iter->first << " {";
shared_ptr<set<line_no>> text_locs = iter->second;
set<line_no>::iterator loc_iter = text_locs->cbegin();
set<line_no>::iterator loc_iter_end = text_locs->cend();
while (loc_iter != loc_iter_end)
{
cout << *loc_iter;
if (++loc_iter_end != loc_iter_end)
cout << ", ";
}
cout << "}\n";
}
cout << endl;
}
QueryResult.h
#ifndef QUERYRESULT_H
#define QUERYRESULT_H
#include <memory>
#include <string>
#include <vector>
#include <set>
#include <iostream>
using std::map;
using std::ostream;
using std::set;
using std::shared_ptr;
using std::string;
using std::vector;
class QueryResult
{
friend ostream &print(ostream &, const QueryResult &);
public:
typedef size_t line_no;
typedef set<line_no>::const_iterator line_it;
public:
QueryResult(string s,
shared_ptr<set<line_no>> p,
shared_ptr<vector<string>> f)
: sought(s),
lines(p),
file(f)
{
}
line_no size() const { return lines->size(); }
line_it begin() const { return lines->cbegin(); }
line_it end() const { return lines->cend(); }
shared_ptr<vector<string>> get_file() { return file; };
private:
string sought; //查询哪个单词
shared_ptr<set<line_no>> lines; //单词所在的行--已经存储在set集合中了
shared_ptr<vector<string>> file; //指向文件内容
};
ostream &print(ostream &, const QueryResult &);
#endif