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 
#include 
#include 
#include 

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 

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 
#include 
#include 

using namespace std;

int main()
{
	int n = 5;
	allocator 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 
#include 
#include 
#include 
#include 
#include 

class QueryResult;

class TextQuery
{
public:
	using line_no = std::vector::size_type;
	TextQuery(std::ifstream&);
	QueryResult query(const std::string& s) const;

private:
	std::shared_ptr> file;
	std::map>> wm;
};

class QueryResult
{
public:
	friend std::ostream& print(std::ostream&, const QueryResult&);
	QueryResult(std::string s,
				std::shared_ptr> p,
				std::shared_ptr> f) :
		sought(s), lines(p), file(f) 
	{}

private:
	std::string sought;
	std::shared_ptr> lines;
	std::shared_ptr> file;
};

std::ostream& print(std::ostream&, const QueryResult&);

#endif

实现

#include "exercise12_27.h"
#include 
#include 
#include 
#include 

using namespace std;

TextQuery::TextQuery(ifstream& ifs) : file(new vector)
{
	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);
			lines->insert(n);
		}
	}
}

QueryResult TextQuery::query(const string& s) const
{
	static shared_ptr> nodata(new set);
	auto loc = wm.find(s);
	if (loc == wm.end())
		return QueryResult(s, nodata, file);
	else
		return 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 
#include 
#include 
#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 
using std::string;

#include 
using std::vector;

#include 
using std::shared_ptr;

#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
	std::ifstream file("./data/storyDataFile.txt");
	vector input;
	std::map> 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 
#include 
#include 
#include 
#include 
#include 

class QueryResult;

class TextQuery
{
public:
	using line_no = std::vector::size_type;
	TextQuery(std::ifstream&);
	QueryResult query(const std::string& s) const;

private:
	std::shared_ptr> file;
	std::map>> wm;
};

class QueryResult
{
public:
	friend std::ostream& print(std::ostream&, const QueryResult&);
	QueryResult(std::string s,
				std::shared_ptr> p,
				std::shared_ptr> f) :
		sought(s), lines(p), file(f) 
	{}

private:
	std::string sought;
	std::shared_ptr> lines;
	std::shared_ptr> file;
};

std::ostream& print(std::ostream&, const QueryResult&);

#endif

实现

#include "exercise12_27.h"
#include 
#include 
#include 
#include 

using namespace std;

TextQuery::TextQuery(ifstream& ifs) : file(new vector)
{
	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);
			lines->insert(n);
		}
	}
}

QueryResult TextQuery::query(const string& s) const
{
	static shared_ptr> nodata(new set);
	auto loc = wm.find(s);
	if (loc == wm.end())
		return QueryResult(s, nodata, file);
	else
		return 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 
#include 
#include 
#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;
}

你可能感兴趣的:(C++《i+1》,c++,开发语言)