C++ Primer(第5版) 练习 12.20
练习 12.20 编写程序,逐行读入一个输入文件,将内容存入一个StrBlob中,用一个StrBlobPtr打印出StrBlob中的每个元素。
环境:Linux Ubuntu(云服务器)
工具:vim
代码块
/*************************************************************************
> File Name: ex12.20.cpp
> Author:
> Mail:
> Created Time: Thu 18 Apr 2024 09:15:15 AM CST
************************************************************************/
#include<iostream>
#include<fstream>
#include<sstream>
#include<string>
#include<vector>
#include<memory>
using namespace std;
class StrBlobPtr;
class StrBlob{
friend class StrBlobPtr;
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();
string &back();
string &front() const;
string &back() const;
StrBlobPtr begin();
StrBlobPtr end();
private:
shared_ptr<vector<string>> data;
void check(size_type i, const string &msg) const;
};
void StrBlob::pop_back(){
check(0, "pop_back on empty StrBlob");
data->pop_back();
}
string& StrBlob::front(){
check(0, "front on empty StrBlob");
return data->front();
}
string& StrBlob::back(){
check(0, "back on empty StrBlob");
return data->back();
}
string& StrBlob::front() const{
check(0, "front on empty StrBlob");
return data->front();
}
string& StrBlob::back() const{
check(0, "back on empty StrBlob");
return data->back();
}
void StrBlob::check(size_type i, const string &msg) const{
if(i >= data->size()){
throw out_of_range(msg);
}
}
class StrBlobPtr{
friend bool compare(StrBlobPtr &a, const StrBlobPtr &b);
public:
StrBlobPtr(): curr(0) {}
StrBlobPtr(StrBlob &s, size_t sz = 0): wptr(s.data), curr(sz) {}
string &deref() const;
StrBlobPtr &incr();
private:
shared_ptr<vector<string>> check(size_t, const string &) const;
weak_ptr<vector<string>> wptr;
size_t curr;
};
shared_ptr<vector<string>> StrBlobPtr::check(size_t i, const string &msg) const {
auto ret = wptr.lock();
if(!ret){
throw runtime_error("unbound StrBlobPtr");
}
if(i >= ret->size()){
throw out_of_range(msg);
}
return ret;
}
string &StrBlobPtr::deref() const{
auto p = check(curr, "dereference past end");
return (*p)[curr];
}
StrBlobPtr &StrBlobPtr::incr(){
check(curr, "increment past end of StrBlobPtr");
++curr;
return *this;
}
StrBlobPtr StrBlob::begin(){
return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end(){
return StrBlobPtr(*this, data->size());
}
bool compare(StrBlobPtr &a, const StrBlobPtr &b){
if(a.wptr.lock() == b.wptr.lock() && a.curr == b.curr){
return true;
}
return false;
}
int main(){
ifstream in("12.20.txt");
StrBlob file;
string str;
StrBlobPtr nFile(file);
while(getline(in, str)){
file.push_back(str);
}
for(auto it = file.begin(); !compare(it, file.end()); it.incr()){
cout<<it.deref()<<" ";
}
cout<<endl;
in.close();
return 0;
}