> 文章列表 > C++ Primer第五版_第十二章习题答案(21~30)

C++ Primer第五版_第十二章习题答案(21~30)

C++ Primer第五版_第十二章习题答案(21~30)

文章目录

      • 练习12.21
      • 练习12.22
      • 练习12.23
      • 练习12.24
      • 练习12.25
      • 练习12.26
      • 练习12.27
      • 练习12.28
      • 练习12.29
      • 练习12.30
        • 头文件
        • 实现
        • 主函数

练习12.21

也可以这样编写 StrBlobPtr 的 deref 成员:

std::string& deref() const {return (*check(curr, "dereference past end"))[curr];
}

你认为哪个版本更好?为什么?

原来的版本更好,可读性更高。

练习12.22

为了能让 StrBlobPtr 使用 const StrBlob,你觉得应该如何修改?定义一个名为ConstStrBlobPtr 的类,使其能够指向 const StrBlob。

构造函数改为接受 const Strblob & , 然后给 Strblob 类添加两个 const 成员函数 cbegin 和 cend,返回 ConstStrBlobPtr。

练习12.23

编写一个程序,连接两个字符串字面常量,将结果保存在一个动态分配的char数组中。重写这个程序,连接两个标准库string对象。

#include <iostream>
#include <string>
#include <cstring>
#include <memory>int main() {const char *c1 = "Hello ";const char *c2 = "World";unsigned len = strlen(c1) + strlen(c2) + 1;char *r = new char[len]();strcat_s(r, len, c1);strcat_s(r, len, c2);std::cout << r << std::endl;std::string s1 = "Hello ";std::string s2 = "World";strcpy_s(r, len, (s1 + s2).c_str());std::cout << r << std::endl;delete[] r;return 0;
}

练习12.24

编写一个程序,从标准输入读取一个字符串,存入一个动态分配的字符数组中。描述你的程序如何处理变长输入。测试你的程序,输入一个超出你分配的数组长度的字符串。

#include <iostream>int main()
{std::cout << "How long do you want the string? ";int size{ 0 };std::cin >> size;char *input = new char[size + 1]();std::cin.ignore();std::cout << "input the string: ";std::cin.get(input, size + 1);std::cout << input;delete[] input;return 0;
}

练习12.25

给定下面的new表达式,你应该如何释放pa?

int *pa = new int[10];
delete [] pa;

练习12.26

用 allocator 重写第427页中的程序。

#include <iostream>
#include <string>
#include <memory>using namespace std;int main()
{int n = 5;allocator<string> alloc;auto p = alloc.allocate(n);string s;auto q = p;while (cin >> s && q != p + n){alloc.construct(q++, s);}while (q != p){std::cout << *--q << " ";alloc.destroy(q);}alloc.deallocate(p, n);return 0;
}

练习12.27

TextQuery 和 QueryResult 类只使用了我们已经介绍过的语言和标准库特性。不要提前看后续章节内容,只用已经学到的知识对这两个类编写你自己的版本。

头文件

#ifndef EX12_27_H
#define EX12_27_H#include <fstream>
#include <memory>
#include <vector>
#include <string>
#include <map>
#include <set>class QueryResult;class TextQuery
{
public:using line_no = std::vector<std::string>::size_type;TextQuery(std::ifstream&);QueryResult query(const std::string& s) const;private:std::shared_ptr<std::vector<std::string>> file;std::map<std::string, std::shared_ptr<std::set<line_no>>> wm;
};class QueryResult
{
public:friend std::ostream& print(std::ostream&, const QueryResult&);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;
};std::ostream& print(std::ostream&, const QueryResult&);#endif

实现

#include "exercise12_27.h"
#include <sstream>
#include <fstream>
#include <vector>
#include <string>using namespace std;TextQuery::TextQuery(ifstream& ifs) : file(new vector<string>)
{string text;while (getline(ifs, text)){file->push_back(text);int n = file->size() - 1;istringstream line(text);string word;while (line >> word){auto &lines = wm[word];if (!lines)lines.reset(new set<line_no>);lines->insert(n);}}
}QueryResult TextQuery::query(const string& s) const
{static shared_ptr<set<line_no>> nodata(new set<line_no>);auto loc = wm.find(s);if (loc == wm.end())return QueryResult(s, nodata, file);elsereturn QueryResult(s, loc->second, file);
}std::ostream& print(std::ostream& os, const QueryResult& qr)
{os << qr.sought << " occurs " << qr.lines->size() << " "<< "time" << (qr.lines->size() > 1 ? "s" : "") << endl;for (auto num : *qr.lines)os << "\\t(line " << num + 1 << ") " << *(qr.file->begin() + num) << endl;return os;
}

主函数

#include <iostream>
#include <string>
#include <fstream>
#include "exercise12_27.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()
{ifstream ifs("./data/storyDataFile.txt");runQueries(ifs);return 0;
}

练习12.28

编写程序实现文本查询,不要定义类来管理数据。你的程序应该接受一个文件,并与用户交互来查询单词。使用vector、map 和 set 容器来保存来自文件的数据并生成查询结果。

#include <string>
using std::string;#include <vector>
using std::vector;#include <memory>
using std::shared_ptr;#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
#include <set>
#include <algorithm>int main()
{std::ifstream file("./data/storyDataFile.txt");vector<string> input;std::map<string, std::set<decltype(input.size())>> dictionary;decltype(input.size()) lineNo{ 0 };for (string line; std::getline(file, line); ++lineNo){input.push_back(line);std::istringstream line_stream(line);for (string text, word; line_stream >> text; word.clear()){std::remove_copy_if(text.begin(), text.end(), std::back_inserter(word), ispunct);dictionary[word].insert(lineNo);}}while (true){std::cout << "enter word to look for, or q to quit: ";string s;if (!(std::cin >> s) || s == "q") break;auto found = dictionary.find(s);if (found != dictionary.end()){std::cout << s << " occurs " << found->second.size() << (found->second.size() > 1 ? " times" : " time") << std::endl;for (auto i : found->second)std::cout << "\\t(line " << i + 1 << ") " << input.at(i) << std::endl;}else std::cout << s << " occurs 0 time" << std::endl;}
}

练习12.29

我们曾经用do while 循环来编写管理用户交互的循环。用do while 重写本节程序,解释你倾向于哪个版本,为什么?

do {std::cout << "enter word to look for, or q to quit: ";string s;if (!(std::cin >> s) || s == "q") break;print(std::cout, tq.query(s)) << std::endl;
} while ( true );

我更喜欢 while,这可能是习惯的问题。

练习12.30

定义你自己版本的 TextQuery 和 QueryResult 类,并执行12.3.1节中的runQueries 函数。

头文件

#ifndef EX12_27_H
#define EX12_27_H#include <fstream>
#include <memory>
#include <vector>
#include <string>
#include <map>
#include <set>class QueryResult;class TextQuery
{
public:using line_no = std::vector<std::string>::size_type;TextQuery(std::ifstream&);QueryResult query(const std::string& s) const;private:std::shared_ptr<std::vector<std::string>> file;std::map<std::string, std::shared_ptr<std::set<line_no>>> wm;
};class QueryResult
{
public:friend std::ostream& print(std::ostream&, const QueryResult&);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;
};std::ostream& print(std::ostream&, const QueryResult&);#endif

实现

#include "exercise12_27.h"
#include <sstream>
#include <fstream>
#include <vector>
#include <string>using namespace std;TextQuery::TextQuery(ifstream& ifs) : file(new vector<string>)
{string text;while (getline(ifs, text)){file->push_back(text);int n = file->size() - 1;istringstream line(text);string word;while (line >> word){auto &lines = wm[word];if (!lines)lines.reset(new set<line_no>);lines->insert(n);}}
}QueryResult TextQuery::query(const string& s) const
{static shared_ptr<set<line_no>> nodata(new set<line_no>);auto loc = wm.find(s);if (loc == wm.end())return QueryResult(s, nodata, file);elsereturn QueryResult(s, loc->second, file);
}std::ostream& print(std::ostream& os, const QueryResult& qr)
{os << qr.sought << " occurs " << qr.lines->size() << " "<< "time" << (qr.lines->size() > 1 ? "s" : "") << endl;for (auto num : *qr.lines)os << "\\t(line " << num + 1 << ") " << *(qr.file->begin() + num) << endl;return os;
}

主函数

#include <iostream>
#include <string>
#include <fstream>
#include "exercise12_27.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()
{ifstream ifs("./data/storyDataFile.txt");runQueries(ifs);return 0;
}