C++ Primer第5版 习题答案 第十二章

目录

第十二章 动态内存

12.1 动态内存与智能指针

12.1.1 shared_ptr类(12.1 ~ 12.5)

12.1.2 直接管理内存(12.6 ~ 12.9)

12.1.3 shared_ptr和new结合使用(12.10 ~ 12.13)

12.1.4 智能指针和异常(12.14 ~ 12.15)

12.1.5 unique_ptr(12.16 ~ 12.18)

12.1.6 weak_ptr(12.19 ~ 12.22)

12.2 动态数组

12.2.1 new和数组(12.23 ~ 12.25)

12.2.2 allocator(12.26)

12.3 使用标准库:文本查询程序

12.3.1 文本查询程序设计(12.27 ~ 12.29)

12.3.2 文本查询程序类的定义(12.30 ~ 12.33)


工作的间隙看的,所以输出比较慢,希望能巩固基础,再往后深入。

一直有参考这位同学的blog的答案:C++Primer第五版——习题答案+详解(完整版)_MISAYAONE的博客-CSDN博客,不过好像这位同学看的很快有很一些些不是很正确,看评论也有都一一修正(收费了,又找了这个:安月月 - 博客园,又顺藤摸瓜找到了这个:GitHub - Mooophy/Cpp-Primer: C++ Primer 5 answers,YYDS~)。

这个答案也是自己看书然后输出的,也可能有问题,如果有发现什么问题,欢迎评论一起讨论!!

默认大家都有了第5版的纸质书或电子书,这里就只记录题号和答案(其实对原书的截图有点侵犯版权的感觉,狗头保命)

第十二章 动态内存

12.1 动态内存与智能指针

12.1.1 shared_ptr类(12.1 ~ 12.5)

12.1:

b1和b2都包含4个元素。

12.2:

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();
}

12.3:

不需要,因为这两个函数都不会对参数进行修改。

12.4:

因为data_size类型是size_type,是一个无符号类型,即使是负数,也会自动转化为非负。

12.5:

explicit的作用就是抑制构造函数的隐式转换。

优点:不会自动的进行类型转换,必须清楚的知道类类型。

缺点:必须用构造函数显示创建一个对象,不够方便简单。

12.1.2 直接管理内存(12.6 ~ 12.9)

12.6:

void Input(vector<int>* ivec){
    if(!ivec) return;
    string s;
    while(cin >> s){
        stringstream a(s);
        int i;
        a >> i;
        ivec->push_back(i);
    }
}

void Output(vector<int>* ivec) {
    if(!ivec) return;
    for(const auto& i : *ivec){
        cout << i << " ";
    }
    cout << endl;
}

int main() {
    auto ivec = IntVectorPointerFactory();
    Input(ivec);
    Output(ivec);
    delete ivec;
    ivec = nullptr;
}
// 1 1 1 sdf
// ^Z
// 1 1 1 0

12.7:

shared_ptr<vector<int>> IntVectorPointerFactory(){
    return make_shared<vector<int>>();
}

void Input(const shared_ptr<vector<int>>& ivec){
    if(!ivec) return;
    string s;
    while(cin >> s){
        stringstream a(s);
        int i;
        a >> i;
        ivec->push_back(i);
    }
}

void Output(const shared_ptr<vector<int>>& ivec) {
    if(!ivec) return;
    for(const auto& i : *ivec){
        cout << i << " ";
    }
    cout << endl;
}

int main() {
    auto ivec = IntVectorPointerFactory();
    Input(ivec);
    Output(ivec);
}
// 1 1 1 sdf
// ^Z
// 1 1 1 0

12.8:

p的类型是int*,函数返回值却是bool型。(错误答案)

p是一个内置类型的指针,返回p会使得p的类型转化为bool类型,其指向的动态内存空间将无法得到释放。

12.9:

r = q,r指向q指向的内存地址,r原指向的内存未发生任何改变;(补充:r原来指向的内存空间将得不到释放,造成内存泄漏)

r2 = q2,q2智能指针的引用计数加一,r2智能指针的引用计数减一,原指针指向的内存释放,现r2指针指向q2。

12.1.3 shared_ptr和new结合使用(12.10 ~ 12.13)

12.10:

正确的,shared_ptr<int> p(new int(42)),引用计数+1,shared_ptr<int>(p)引用计数+1,process调用后,引用计数减1,最后还剩1,可以正确使用。

12.11:

process调用结束后,指针析构,p被销毁,p指向的内存被释放了,再使用p就是未定义。

12.12:

(a) 合法,复制sp引用计数+1,调用完引用计数-1,不影响原sp的使用。

(b) 不合法,不能传递内置指针给shared_ptr,无法隐式转换。

(c) 不合法,与(b)同样的原因,不能传递内置指针给shared_ptr,无法隐式转换。

(d) 合法,但process调用完后不能再使用p,因为p指向的内存被释放。

12.13:

抄的答案:删除p之后,会导致p指向的内存被释放,此时sp就会变成空悬指针,在sp指针被销毁时,该块内存会被二次delete,执行后产生错误:double free

12.1.4 智能指针和异常(12.14 ~ 12.15)

12.14:

没有想到其他写法。

12.15:

void f(destination &d /* 其他参数 */) {
	connection c = connect(&d);
    shared_ptr<connection> p(&c , [](connection *p){
        disconnect(*p);
    });
}

12.1.5 unique_ptr(12.16 ~ 12.18)

12.16:

unique_ptr<int> p1(new int(10));
unique_ptr<int> p2(p1);
// unique_ptr<int> p2 = p1;

error: use of deleted function 'std::unique_ptr<Tp, _Dp>::unique_ptr(const std::unique_ptr<Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]'|

以下网上答案,没理解

error C2248: “std::unique_ptr<Ty>::unique_ptr”: 无法访问 private 成员(在“std::unique_ptr<Ty>”类中声明)

12.17:

(a)不合法,不能用对象初始化unique_ptr;

(b)合法,pi野指针;

(c)合法,pi2野指针;

(d)合法,ix对象被清空;

(e)合法;

(f)不合法,一块内存对象只能被一个unique_ptr持有。

和网络答案不一致,但也没有很理解,以上为个人理解,欢迎指正。

12.18:

shared_ptr指向的对象可以同时被多个shared_ptr持有,release会将指针置为空,导致其他持有这个指针的shared_ptr对象失效。

12.1.6 weak_ptr(12.19 ~ 12.22)

12.19:

// 这里的代码主要有两个问题
// 1.循环引用 可以在类中声明 在StrBlobPtr后再定义begin end
// 2.需要额外给StrBlobPtr类添加pos函数来比较
class StrBlobPtr;
class StrBlob {
public:
    typedef std::vector<std::string>::size_type size_type;
    friend class StrBlobPtr;
    StrBlob();
    StrBlob(std::initializer_list<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();
    StrBlobPtr begin();
    StrBlobPtr end();
private:
    std::shared_ptr<std::vector<std::string>> data;
    void check(size_type i, const std::string& msg) const;
};

StrBlob::StrBlob() : data(make_shared<vector<string>>()) {

}

StrBlob::StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {

}

string& StrBlob::front() {
    check(0, "front on empty StrBlob");
    return data->front();
}

string& StrBlob::back() {
    check(0, "back on empty StrBlob");
    return data->back();
}

void StrBlob::pop_back() {
    check(0, "pop_back on empty StrBlob");
    data->pop_back();
}

void StrBlob::check(size_type i, const string& msg) const {
    if(i >= data->size()) {
        throw out_of_range(msg);
    }
}

class StrBlobPtr {
public:
    StrBlobPtr() : curr(0) { }
    StrBlobPtr(StrBlob &a, size_t sz = 0) : wptr(a.data), curr(sz) { }
    std::string& deref() const;
    StrBlobPtr& incr();
    size_t pos() const;
private:
    std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string&) const;
    std::weak_ptr<std::vector<std::string>> wptr;
    std::size_t curr;
};

std::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;
}

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;
}

size_t StrBlobPtr::pos() const {
    return curr;
}

StrBlobPtr StrBlob::begin() {
    return StrBlobPtr(*this);
}

StrBlobPtr StrBlob::end() {
    auto ret = StrBlobPtr(*this, data->size());
    return ret;
}

12.20:

int main() {
    std::string str{};
    StrBlob str_blob{};
    while(cin >> str) {
        str_blob.push_back(str);
    }
    for (StrBlobPtr pbeg(str_blob.begin()), pend(str_blob.end()); pbeg.pos() != pend.pos(); pbeg.incr()) {
        cout << pbeg.deref() << std::endl;
    }
}

12.21:

将合法性检查与元素获取的返回语句分离开来,代码更清晰易读。

12.22:

StrBlobPtr(const StrBlob &a, size_t sz = 0) : wptr(a.data), curr(sz) { }

12.2 动态数组

12.2.1 new和数组(12.23 ~ 12.25)

12.23:

// dynamically allocated array of char
char *concatenate_string = new char[strlen("hello " "world") + 1]();
strcat(concatenate_string, "hello ");
strcat(concatenate_string, "world");
std::cout << concatenate_string << std::endl;
delete [] concatenate_string;

// std::string
std::string str1{ "hello " }, str2{ "world" };
std::cout << str1 + str2 << std::endl;

// hello world
// hello world
// copy from https://github.com/Mooophy/Cpp-Primer/blob/master/ch12/ex12_23.cpp

12.24:

string str;
cin >> str;
char *input = new char[str.size() + 1]();
strcat(input, str.c_str());
cout << input << endl;
delete [] input;
// input: helloworld
// output: helloworld

12.25:

delete [] pa;

12.2.2 allocator(12.26)

12.26:

allocator<string> alloc;           // 可以分配string的allocator对象
auto const p = alloc.allocate(n);  // 分配n个未初始化的string
string s;
auto q = p;
while(cin >> s && q != p + n)
    alloc.construct(q++, s);

// 输出 & 析构
while(q != p) {
    cout << *--q << endl;
    alloc.destroy(q);
}

// 释放内存
alloc.deallocate(p, n);

12.3 使用标准库:文本查询程序

12.3.1 文本查询程序设计(12.27 ~ 12.29)

12.27:

class TextQuery{
public:
    TextQuery(ifstream &infile);
    void query(string s);

private:
    vector<string> line_text_{};
    map<string, set<size_t>> word_lines_{};
};

TextQuery::TextQuery(ifstream &infile){
    string line_string;
    size_t line = 1;
    while(getline(infile, line_string)){
        cout << line_string << endl;
        line_text_.push_back(line_string);
        istringstream stream(line_string);
        string word;
        while(stream >> word){
            auto iter = word_lines_.find(word);
            set<size_t> lines{};
            if(iter != word_lines_.end()) {
                lines = iter->second;
            }
            lines.insert(line);
            word_lines_[word] = lines;
        }
        line++;
    }
}

void TextQuery::query(string s) {
    auto iter = word_lines_.find(s);
    if(iter != word_lines_.end()){
        auto lines = iter->second;
        cout << s << " occurs " << lines.size() << " times" << endl;
        for(const auto index : lines) {
            if(index >= 1 && index <= line_text_.size()){
                cout << "(line "<< index << ") " << line_text_[index - 1] << endl;
            }
        }
    }

}

void runQueries(ifstream &infile) {
    // infile 是一个ifstream,指向我们要处理的文件
    TextQuery tq(infile);  // 保存文件并建立查询map
    // 与用户交互:提示用户输入要查询的单词,完成查询并打印结果
    while(true) {
        cout << "enter word to look for, or q to quit: ";
        string s;
        // 若遇到文件尾或用户输入了'q'时循环终止
        if(!(cin >> s) || s == "q") break;
        // 指向查询并打印结果
        //print(cout, tq.query(s)) << endl;
         tq.query(s);
    }
}

int main() {
    ifstream fstrm1("1.txt");
    runQueries(fstrm1);
}

// 自己写的 有点简单 只用了一个类 也没有用到智能指针
// 输入是文件1.txt 会打印出输入的内容
/*
brb be right back
k okay?
y why
r are
u you
pic picture
thk thanks~
18r later
k okay!
enter word to look for, or q to quit: k
k occurs 2 times
(line 2) k okay?
(line 9) k okay!
enter word to look for, or q to quit: r
r occurs 1 times
(line 4) r are
enter word to look for, or q to quit: q
*/
// https://github.com/Mooophy/Cpp-Primer/tree/master/ch12 移除了输入中的标点符号

12.28:

int main() {
    ifstream fstrm1("1.txt");

    vector<string> line_text{};
    map<string, set<size_t>> word_lines{};

    string line_string;
    size_t line = 1;
    while(getline(fstrm1, line_string)){
        cout << line_string << endl;
        line_text.push_back(line_string);
        istringstream stream(line_string);
        string word;
        while(stream >> word){
            auto iter = word_lines.find(word);
            set<size_t> lines{};
            if(iter != word_lines.end()) {
                lines = iter->second;
            }
            lines.insert(line);
            word_lines[word] = lines;
        }
        line++;
    }

    while(true) {
        cout << "enter word to look for, or q to quit: ";
        string s;
        // 若遇到文件尾或用户输入了'q'时循环终止
        if(!(cin >> s) || s == "q") break;
        // 指向查询并打印结果
        //print(cout, tq.query(s)) << endl;
        auto iter = word_lines.find(s);
        if(iter != word_lines.end()){
            auto lines = iter->second;
            cout << s << " occurs " << lines.size() << " times" << endl;
            for(const auto index : lines) {
                if(index >= 1 && index <= line_text.size()){
                    cout << "(line "<< index << ") " << line_text[index - 1] << endl;
                }
            }
        }
    }
}

// 输出与上面一致

12.29:

void runQueries(ifstream &infile) {
    // infile 是一个ifstream,指向我们要处理的文件
    TextQuery tq(infile);  // 保存文件并建立查询map
    // 与用户交互:提示用户输入要查询的单词,完成查询并打印结果

    do{
        cout << "enter word to look for, or q to quit: ";
        string s;
        // 若遇到文件尾或用户输入了'q'时循环终止
        if(!(cin >> s) || s == "q") break;
        // 指向查询并打印结果
        //print(cout, tq.query(s)) << endl;
        tq.query(s);
    }
    while(true);
}

// 倾向于直接用while,清晰
// https://www.cnblogs.com/songshuguiyu/p/9598196.html 这里写do while更简洁…

12.3.2 文本查询程序类的定义(12.30 ~ 12.33)

12.30:

class QueryResult;  // 为了定义函数query的返回类型
class TextQuery {
public:
    using line_no = std::vector<std::string>::size_type;
    TextQuery(std::ifstream&);
    QueryResult query(const std::string&) const;
private:
    std::shared_ptr<std::vector<std::string>> file;  // 输入文件
    // 每个单词到它所在的行号的集合的映射
    std::map<std::string, std::shared_ptr<std::set<line_no>>> wm;
};

TextQuery::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) {  // 对行中每个单词
    		// 如果单词不在wm中,以之为下标在wm中添加一项
            auto &lines = wm[word];  // lines是shared_ptr(如果lines为空没有使用引用是会失败的)
            if(!lines)  // 在第一次遇到此单词时,此指针为空
                lines.reset(new set<line_no>);  // 分配一个新的set
            lines->insert(n);  // 将此行号插入set中
        }
    }
}

class QueryResult {
    friend std::ostream& print(std::ostream&, const QueryResult&);  // 友元函数不需要放在public或private里吗?
public:
    QueryResult(std::string s, std::shared_ptr<std::set<TextQuery::line_no>> p, std::shared_ptr<std::vector<std::string>> f) : sought(s), lines(p), file(f) { }
private:
    std::string sought;  // 查询单词
    std::shared_ptr<std::set<TextQuery::line_no>> lines;  // 出现的行号
    std::shared_ptr<std::vector<std::string>> file;  // 输入文字
};

QueryResult TextQuery::query(const string & sought) const {
    // 如果未找到sought,将返回指向此set的指针
    static shared_ptr<set<line_no>> nodata(new set<line_no>);
    // 使用find而不是下标运算符来查找单词,避免将单词添加到wm中!
    auto loc = wm.find(sought);
    if(loc == wm.end())
        return QueryResult(sought, nodata, file);  // 未找到
    else
        return QueryResult(sought, loc->second, file);
}

void runQueries(ifstream &infile) {
    // infile 是一个ifstream,指向我们要处理的文件
    TextQuery tq(infile);  // 保存文件并建立查询map
    // 与用户交互:提示用户输入要查询的单词,完成查询并打印结果
    while(true) {
        cout << "enter word to look for, or q to quit: ";
        string s;
        // 若遇到文件尾或用户输入了'q'时循环终止
        if(!(cin >> s) || s == "q") break;
        // 指向查询并打印结果
        print(cout, tq.query(s)) << endl;
    }
}

string make_plural(size_t ctr, const string &word, const string &ending) {
    return ctr > 1 ? word + ending : word;
}

ostream &print(ostream &os, const QueryResult &qr) {
    // 如果找到了单词,打印出现次数和所有出现的位置
    os << qr.sought << " occurs " << qr.lines->size() << " " << make_plural(qr.lines->size(), "times", "s") << endl;
    // 打印单词出现的每一行
    for(auto num : *qr.lines)  // 对set中每个单词
        // 避免行号从0开始给用户带来的困惑
        os << "\t(line " << num + 1 << ") " << *(qr.file->begin() + num) << endl;
    return os;
}

int main() {
    ifstream fstrm1("1.txt");
    runQueries(fstrm1);
}
// 12.27写过了,这里将书中的代码copy运行

12.31:

一行中有两个重复的单词,输出时,如果vector不过滤,会将这一行输出两遍,使用set不用过滤。

12.32:

class StrBlobPtr;

class StrBlob {
public:
    typedef std::vector<std::string>::size_type size_type;
    friend class StrBlobPtr;
    StrBlob();
    StrBlob(std::initializer_list<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();
    StrBlobPtr begin();
    StrBlobPtr end();
private:
    std::shared_ptr<std::vector<std::string>> data;
    void check(size_type i, const std::string& msg) const;
};

StrBlob::StrBlob() : data(make_shared<vector<string>>()) {

}

StrBlob::StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {

}

string& StrBlob::front() {
    check(0, "front on empty StrBlob");
    return data->front();
}

string& StrBlob::back() {
    check(0, "back on empty StrBlob");
    return data->back();
}

void StrBlob::pop_back() {
    check(0, "pop_back on empty StrBlob");
    data->pop_back();
}

void StrBlob::check(size_type i, const string& msg) const {
    if(i >= data->size()) {
        throw out_of_range(msg);
    }
}

class StrBlobPtr {
public:
    StrBlobPtr() : curr(0) { }
    StrBlobPtr(const StrBlob &a, size_t sz = 0) : wptr(a.data), curr(sz) { }
    std::string& deref() const;
    StrBlobPtr& incr();
    size_t pos() const;
private:
    std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string&) const;
    std::weak_ptr<std::vector<std::string>> wptr;
    std::size_t curr;
};

std::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;
}

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;
}

size_t StrBlobPtr::pos() const {
    return curr;
}

StrBlobPtr StrBlob::begin() {
    return StrBlobPtr(*this);
}

StrBlobPtr StrBlob::end() {
    auto ret = StrBlobPtr(*this, data->size());
    return ret;
}

class QueryResult;  // 为了定义函数query的返回类型
class TextQuery {
public:
    using line_no = std::vector<std::string>::size_type;
    TextQuery(std::ifstream&);
    QueryResult query(const std::string&) const;
private:
    std::shared_ptr<std::vector<std::string>> file;  // 输入文件
    std::shared_ptr<StrBlob> file2;
    // 每个单词到它所在的行号的集合的映射
    std::map<std::string, std::shared_ptr<std::set<line_no>>> wm;
};

TextQuery::TextQuery(ifstream &is) : file2(make_shared<StrBlob>()) {
	string text;
    while(getline(is, text)) {     // 对文件中每一行
        file2->push_back(text);     // 保存此行文本
        int n = file2->size() - 1;  // 当前行号
        istringstream line(text);  // 将行文本分解为单词
        string word;
        while(line >> word) {  // 对行中每个单词
    		// 如果单词不在wm中,以之为下标在wm中添加一项
            auto &lines = wm[word];  // lines是shared_ptr(如果lines为空没有使用引用是会失败的)
            if(!lines)  // 在第一次遇到此单词时,此指针为空
                lines.reset(new set<line_no>);  // 分配一个新的set
            lines->insert(n);  // 将此行号插入set中
        }
    }
}

class QueryResult {
    friend std::ostream& print(std::ostream&, const QueryResult&);  // 友元函数不需要放在public或private里吗?
public:
    QueryResult(std::string s, std::shared_ptr<std::set<TextQuery::line_no>> p, std::shared_ptr<StrBlob> f) : sought(s), lines(p), file2(f) { }
private:
    std::string sought;  // 查询单词
    std::shared_ptr<std::set<TextQuery::line_no>> lines;  // 出现的行号
    std::shared_ptr<std::vector<std::string>> file;  // 输入文字
    std::shared_ptr<StrBlob> file2;  // 输入文字
};

QueryResult TextQuery::query(const string & sought) const {
    // 如果未找到sought,将返回指向此set的指针
    static shared_ptr<set<line_no>> nodata(new set<line_no>);
    // 使用find而不是下标运算符来查找单词,避免将单词添加到wm中!
    auto loc = wm.find(sought);
    if(loc == wm.end())
        return QueryResult(sought, nodata, file2);  // 未找到
    else
        return QueryResult(sought, loc->second, file2);
}

void runQueries(ifstream &infile) {
    // infile 是一个ifstream,指向我们要处理的文件
    TextQuery tq(infile);  // 保存文件并建立查询map
    // 与用户交互:提示用户输入要查询的单词,完成查询并打印结果
    while(true) {
        cout << "enter word to look for, or q to quit: ";
        string s;
        // 若遇到文件尾或用户输入了'q'时循环终止
        if(!(cin >> s) || s == "q") break;
        // 指向查询并打印结果
        print(cout, tq.query(s)) << endl;
    }
}

string make_plural(size_t ctr, const string &word, const string &ending) {
    return ctr > 1 ? word + ending : word;
}

ostream &print(ostream &os, const QueryResult &qr) {
    // 如果找到了单词,打印出现次数和所有出现的位置
    os << qr.sought << " occurs " << qr.lines->size() << " " << make_plural(qr.lines->size(), "times", "s") << endl;
    // 打印单词出现的每一行
    for(auto num : *qr.lines) { // 对set中每个单词
        // 避免行号从0开始给用户带来的困惑
        StrBlobPtr p(*qr.file2, num);
        os << "\t(line " << num + 1 << ") " << p.deref() << endl;
    }
    return os;
}

int main() {
    ifstream fstrm1("1.txt");
    runQueries(fstrm1);
}
// 将之前的StrBlob和StrBlobPtr也放过来了
// 里面有一些上题无用的变量file没有删哇~

12.33:

class QueryResult {
    using ResultIter = std::set<StrBlob::size_type>::iterator;
    friend std::ostream& print(std::ostream&, const QueryResult&);  // 友元函数不需要放在public或private里吗?
public:
    QueryResult(std::string s, std::shared_ptr<std::set<TextQuery::line_no>> p, std::shared_ptr<StrBlob> f) : sought(s), lines(p), file2(f) { }
    ResultIter begin() const { return nos->begin(); }
    ResultIter end() const { return nos->end(); }
    shared_ptr<StrBlob> get_file() const { return file2; }
private:
    std::string sought;  // 查询单词
    std::shared_ptr<std::set<TextQuery::line_no>> lines;  // 出现的行号
    std::shared_ptr<std::vector<std::string>> file;  // 输入文字
    std::shared_ptr<StrBlob> file2;  // 输入文字
    shared_ptr<std::set<StrBlob::size_type>> nos;
};
// copy了一下这里的https://github.com/Mooophy/Cpp-Primer/blob/master/ch12/ex12_33.h

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值