12.2
#include<iostream>
#include<fstream>
#include<vector>
#include<memory>
#include<string>
using namespace std;
class StrBlob {
public:
typedef vector<string>::size_type size_type;
StrBlob() : data(make_shared<vector<string>>()) {}
StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {}
size_type size() const { return data->size(); }
bool empty() const { return data->empty(); }
void push_back(const string& t) { data->push_back(t); }
void pop_back();
string& front();
const string& front() const;
string& back();
const string& back() const;
private:
shared_ptr<vector<string>> data;
void check(size_type i, const string& smg) const;
};
int main(int argc, char* argv[])
{
StrBlob d({ "2020,7,13", });
cout << d.size() << endl;
d.push_back("2020,7,14");
cout << d.size() << endl;
d.pop_back();
cout << d.size() << endl;
return 0;
}
void StrBlob::check(size_type i, const string& msg) const
{
if (i >= data->size())
throw out_of_range(msg);
}
void StrBlob::pop_back()
{
check(0, "pop_back on empty StrBlob");
return data->pop_back();
}
string&
StrBlob::front()
{
check(0, "front on empty StrBlob");
return data->front();
}
const string&
StrBlob::front() const
{
check(0, "front on empty StrBlob");
return data->front();
}
string&
StrBlob::back()
{
check(0, "back on empty StrBlob");
return data->back();
}
const string&
StrBlob::back() const
{
check(0, "back on empty StrBlob");
return data->back();
}
12.19 & 12.20
head.h
#include <memory>
#include <vector>
#include <string>
class StrBlobPtr; //友元必须提前声明
class StrBlob {
friend class StrBlobPtr;
public:
typedef std::vector<std::string>::size_type size_type;
StrBlob() :data(std::make_shared<std::vector<std::string>>()) { }
StrBlob(std::initializer_list<std::string>il) :data(std::make_shared<std::vector<std::string>>(il)) { }
size_type size() const { return data->size(); }
bool empty() const { return data->empty(); }
void push_back(const std::string& t) { data->push_back(t); }
void pop_back();
std::string& front();
std::string& back();
const std::string& front() const;
const std::string& back() const;
StrBlobPtr begin();
StrBlobPtr end();
StrBlobPtr cbegin() const;
StrBlobPtr cend() const;
private:
std::shared_ptr<std::vector<std::string>> data;
void check(size_type i, const std::string& msg) const;
};
class StrBlobPtr {
public:
StrBlobPtr() : curr(0) { }
StrBlobPtr(const StrBlob& a, size_t sz = 0) :
wptr(a.data), curr(sz) { }
bool operator != (const StrBlobPtr& q) { return q.curr != curr; }
std::string& deref() const;
StrBlobPtr& incr();
private:
std::shared_ptr<std::vector<std::string>>
check(std::size_t i, const std::string& msg) const;
std::weak_ptr<std::vector<std::string>> wptr;
std::size_t curr;
};
void StrBlob::pop_back()
{
check(0, "pop_back on empty StrBlob");
data->pop_back();
}
std::string&
StrBlob::front()
{
check(0, "front on empty StrBlob");
return data->front();
}
std::string&
StrBlob::back()
{
check(0, "back on empty StrBlob");
return data->back();
}
const std::string&
StrBlob::front() const
{
check(0, "front on empty StrBlob");
return data->front();
}
const std::string&
StrBlob::back() const
{
check(0, "back on empty StrBlob");
return data->back();
}
void StrBlob::check(size_type i, const std::string& msg) const
{
if (i >= data->size())
throw std::out_of_range(msg);
}
StrBlobPtr StrBlob::begin()
{
return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end()
{
auto ret = StrBlobPtr(*this, data->size());
return ret;
}
StrBlobPtr StrBlob::cbegin() const
{
return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::cend() const
{
auto ret = StrBlobPtr(*this, data->size());
return ret;
}
std::string&
StrBlobPtr::deref() const
{
auto p = check(curr, "dereferemce past end");
return (*p)[curr];
}
StrBlobPtr&
StrBlobPtr::incr()
{
check(curr, "increment past end of StrBlobPtr");
++curr;
return *this;
}
std::shared_ptr<std::vector<std::string>>
StrBlobPtr::check(std::size_t i, const std::string& msg) const
{
auto ret = wptr.lock();
if (!ret)
throw std::runtime_error("unbound StrBlobPtr");
if (i >= ret->size())
throw std::out_of_range(msg);
return ret;
}
cpp
#include<iostream>
#include<memory>
#include"head.h"
using namespace std;
int main(int argc, char* argv[])
{
const StrBlob b{ "It", "is", "a", "Test" };
StrBlobPtr q(b);
for (q = b.cbegin(); q != b.cend(); q.incr())
cout << q.deref() << " ";
return 0;
}
12.24
#include<iostream>
#include<memory>
#include<string>
using namespace std;
int main(int argc, char* argv[])
{
allocator<string> alloc;
string s;
size_t i = 9;
auto const p = alloc.allocate(i);
auto q = p;
while (cin >> s && q != p + i)
alloc.construct(q++, s);
const size_t sz = q - p;
cout << sz << endl;
for (size_t i = 0; i != sz; i++)
cout << *(p + i) << endl;
while (q != p)
alloc.destroy(--q);
alloc.deallocate(p, i);
return 0;
}
12.32
StrBlob.h
#include<iostream>
#include<fstream>
#include<vector>
#include<memory>
#include<string>
class StrBlob {
public:
typedef std::vector<std::string>::size_type size_type;
StrBlob() : data(std::make_shared<std::vector<std::string>>()) {}
StrBlob(std::initializer_list<std::string> il) : data(std::make_shared<std::vector<std::string>>(il)) {}
size_type size() const { return data->size(); }
bool empty() const { return data->empty(); }
void push_back(const std::string& t) { data->push_back(t); }
void pop_back();
std::string& front();
const std::string& front() const;
std::string& mid(const int n); //返回对应行号的文本
const std::string& mid(const int n) const;
std::string& back();
const std::string& back() const;
private:
std::shared_ptr<std::vector<std::string>> data;
void check(size_type i, const std::string& smg) const;
};
Query.h
#include<sstream>
#include<map>
#include<set>
#include"StrBlob.h"
class QueryResult;
class TextQuery {
public:
using line_no = std::vector<std::string>::size_type;
TextQuery(std::ifstream&);
QueryResult query(const std::string&) const;
private:
StrBlob file; //输入文件
//每个单词到它所在的行号的集合的映射
std::map<std::string,
std::shared_ptr<std::set<line_no>>> wm;
};
class QueryResult {
friend std::ostream& print(std::ostream&, const QueryResult&);
public:
using line_no = std::vector<std::string>::size_type;
QueryResult(std::string s,
std::shared_ptr<std::set<line_no>> p,
StrBlob f) :
sought(s), lines(p), file(f) {}
private:
std::string sought;
std::shared_ptr<std::set<line_no>> lines;
StrBlob file;
};
fun.cpp
#include"Query.h"
using namespace std;
string make_plural(size_t ctr, const string& word, const string& ending) {
return (ctr > 1) ? word + ending : word;
}
//StrBlob定义
void StrBlob::check(size_type i, const string& msg) const
{
if (i >= data->size())
throw out_of_range(msg);
}
void StrBlob::pop_back()
{
check(0, "pop_back on empty StrBlob");
return data->pop_back();
}
string&
StrBlob::front()
{
check(0, "front on empty StrBlob");
return data->front();
}
const string&
StrBlob::front() const
{
check(0, "front on empty StrBlob");
return data->front();
}
string&
StrBlob::mid(const int n)
{
check(0, "mid on empty StrBlob");
return (*data)[n];
}
const string&
StrBlob::mid(const int n) const
{
check(0, "mid on empty StrBlob");
return (*data)[n];
}
string&
StrBlob::back()
{
check(0, "back on empty StrBlob");
return data->back();
}
const string&
StrBlob::back() const
{
check(0, "back on empty StrBlob");
return data->back();
}
//TextQuery定义
TextQuery::TextQuery(ifstream& is) : file() //初始化智能指针
{
string text;
while (getline(is, text)) {
file.push_back(text);
int n = file.size() - 1; //当前行号
istringstream line(text);
string word;
while (line >> word) {
auto& lines = wm[word]; //对于第一次遇到的单词以之为下标在wm中添加一项
//lines为shared_ptr类,引用wm中的set<size_type>
if (!lines) //如果第一次遇到此单词,即lines为空指针
lines.reset(new set<line_no>);
lines->insert(n);
}
}
}
QueryResult
TextQuery::query(const string& sought) const
{
static shared_ptr<set<line_no>> nodata(new set<line_no>); //shared_ptr管理指向空行号的set
auto loc = wm.find(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(), "line", "s") << endl;
for (auto num : *qr.lines)
os << "\t(line " << num + 1 << ") " << qr.file.mid(num) << endl; //通过行号访问file中对应的行
return os;
}
main.cpp
#include<iostream>
#include"Query.h"
using namespace std;
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 fin("1.txt");
runQueries(fin);
return 0;
}
1.txt
as test as hello hello sad test test
test sad over sks test
sad fill ridge this hello
this dzxg love
test unforgettable
sad is love world
test test file sad file test
as sad file is file file
derive sad love as