C++ Primer第五版_第十九章习题答案(11~20)

news/2024/11/20 4:40:11/

文章目录

      • 练习19.11
      • 练习19.12
      • 练习19.13
      • 练习19.14
      • 练习19.15
      • 练习19.16
      • 练习19.17
      • 练习19.18
      • 练习19.19
      • 练习19.20

练习19.11

普通的数据指针和指向数据成员的指针有何区别?

普通的数据指针指向一个对象;类成员指针指向类的非静态成员。当初始化这样一个指针时,我们令其指向类的某个成员,但是不指定该成员所属的对象;直到使用成员指针时,才提供所属的对象。

练习19.12

定义一个成员指针,令其可以指向 Screen 类的 cursor 成员。通过该指针获得 Screen::cursor 的值。

#include <string>
#include <iostream>class Screen {public:using pos = std::string::size_type;static const std::string Screen::*data() { return &Screen::contents; }static const pos Screen::*pcursor() { return &Screen::cursor; }Screen() = default;Screen(pos ht, pos wd, char c):height(ht), width(wd), contents(ht*wd, c){ }char get() const { return contents[cursor]; }char get(pos r, pos c) const { return contents[r*width+c]; }private:pos cursor = 0;pos height = 0, width = 0;std::string contents;
};int main()
{// const std::string Screen::*pdata;// pdata = &Screen::contents;// auto pdata = &Screen::contents;  //contents is privateconst std::string Screen::*pdata = Screen::data();Screen myScreen(2, 2, 'c');auto s = myScreen.*pdata;std::cout << s << std::endl;const std::string::size_type Screen::*pcursor = Screen::pcursor();auto i = myScreen.*pcursor;std::cout << i << std::endl;return 0;
}

练习19.13

定义一个类型,使其可以表示指向 Sales_data 类的 bookNo 成员的指针。

const std::string Sales_data::*pdata;

练习19.14

下面的代码合法吗?如果合法,代码的含义是什么?如果不合法,解释原因。

auto pmf = &Screen::get_cursor;
pmf = &Screen::get;

不合法,Screen中get_cursor函数返回的为pos类型,get函数返回的为char类型。

练习19.15

普通函数指针和指向成员函数的指针有何区别?

和普通函数指针不同的是,在成员函数和指向该成员的指针之间不存在自动转换规则。

练习19.16

声明一个类型别名,令其作为指向 Sales_data 的 avg_price 成员的指针的同义词。

using AvgPrice = double (Sales_data::*)() const;
AvgPrice avgprice = &Sales_data::avg_price;

练习19.17

为 Screen 的所有成员函数类型各定义一个类型别名。

#include <string>
#include <iostream>class Screen {public:using pos = std::string::size_type;static const std::string Screen::*data() { return &Screen::contents; }static const pos Screen::*pcursor() { return &Screen::cursor; }Screen() = default;Screen(pos ht, pos wd, char c):height(ht), width(wd), contents(ht*wd, c){ }char get() const { return contents[cursor]; }char get(pos r, pos c) const { return contents[r*width+c]; }private:pos cursor = 0;pos height = 0, width = 0;std::string contents;
};int main()
{Screen myScreen(2, 2, 'c');char (Screen::*pmf2)(Screen::pos, Screen::pos) const;pmf2 = &Screen::get;// char c1 = (myScreen.*pmf2)();char c2 = (myScreen.*pmf2)(0, 0);std::cout << c2 << std::endl;using Get1 = char (Screen::*)() const;using Get2 = char (Screen::*)(Screen::pos, Screen::pos) const;Get1 get1 = &Screen::get;Get2 get2 = &Screen::get;std::cout << (myScreen.*get1)() << std::endl;std::cout << (myScreen.*get2)(0, 0) << std::endl;return 0;
}

练习19.18

编写一个函数,使用 count_if 统计在给定的 vector 中有多少个空 string。

#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>int main()
{std::vector<std::string> vs = {"a", "bb", "", "ccc", ""};std::function<bool (const std::string&)> fcn = &std::string::empty;auto it1 = std::find_if(vs.begin(), vs.end(), fcn);std::cout << "function: " << it1 - vs.begin() << std::endl;auto it2 = std::find_if(vs.begin(), vs.end(), std::mem_fn(&std::string::empty));std::cout << "mem_fn: " << it2 - vs.begin() << std::endl;auto it3 = std::find_if(vs.begin(), vs.end(), std::bind(&std::string::empty, std::placeholders::_1));std::cout << "bind: " << it3 - vs.begin() << std::endl;std::cout << "count_if: " << std::count_if(vs.begin(), vs.end(), fcn) << std::endl;return 0;
}

练习19.19

编写一个函数,令其接受vector<Sales_data>并查找平均价格高于某个值的第一个元素。

Sales_data.h

#ifndef SALES_DATA_H_
#define SALES_DATA_H_#include <string>
#include <stdexcept>class isbn_mismatch : public std::logic_error
{
public:explicit isbn_mismatch(const std::string &s) : std::logic_error(s) { }isbn_mismatch(const std::string &s, const std::string &lhs, const std::string &rhs) :std::logic_error(s), left(lhs), right(rhs) { }const std::string left, right;
};struct Sales_data;std::istream &operator>>(std::istream &is, Sales_data &item);
std::ostream &operator<<(std::ostream &os, const Sales_data &item);
Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs);struct Sales_data
{
friend std::istream& operator>>(std::istream&, Sales_data&);
friend std::ostream& operator<<(std::ostream&, const Sales_data&);
friend Sales_data operator+(const Sales_data&, const Sales_data&);
friend bool operator==(const Sales_data&, const Sales_data&);
friend class std::hash<Sales_data>;public:Sales_data(const std::string &s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p*n){std::cout << "Sales_data(const std::string &s, unsigned n, double p)" << std::endl;}Sales_data() : Sales_data("", 0, 0){std::cout << "Sales_data() : Sales_data(\"\", 0, 0)" << std::endl;}Sales_data(const std::string &s) : Sales_data(s, 0, 0){std::cout << "Sales_data(const std::string &s) : Sales_data" << std::endl;}Sales_data(std::istream &is) : Sales_data(){/*read(is, *this);*/ is >> *this; std::cout << "Sales_data(std::istream &is) : Sales_data()" << std::endl;}std::string isbn() const {return bookNo;}Sales_data& operator=(const std::string&);Sales_data& operator+=(const Sales_data&);Sales_data& operator-=(const Sales_data&);// bool higher_avg_price()// {// 	return this->avg_price() > 10;// }bool higher_avg_price(double ref_price){return this->avg_price() > ref_price;}
private:inline double avg_price() const;std::string bookNo;unsigned units_sold = 0;double revenue = 0.0;
};inline double Sales_data::avg_price() const
{if(units_sold)return revenue / units_sold;elsereturn 0;
}Sales_data& Sales_data::operator=(const std::string &s)
{*this = Sales_data(s);return *this;
}Sales_data& Sales_data::operator+=(const Sales_data &rhs)
{if(isbn() != rhs.isbn())throw isbn_mismatch("wrong isbns", isbn(), rhs.isbn());units_sold += rhs.units_sold;revenue += rhs.revenue;return *this;
}Sales_data& Sales_data::operator-=(const Sales_data &rhs)
{units_sold -= rhs.units_sold;revenue -= rhs.revenue;return *this;
}std::istream &operator>>(std::istream &is, Sales_data &item)
{double price = 0;is >> item.bookNo >> item.units_sold >> price;if(is)item.revenue = price * item.units_sold;elseitem = Sales_data();return is;
}std::ostream &operator<<(std::ostream &os, const Sales_data &item)
{os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();return os;
}Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs)
{Sales_data sum = lhs;sum += rhs;return sum;
}bool operator==(const Sales_data &lhs, const Sales_data &rhs)
{return lhs.isbn() == rhs.isbn() && lhs.units_sold == rhs.units_sold && lhs.revenue == rhs.revenue;
}#endif

练习19.20

将你的 QueryResult 类嵌套在 TextQuery 中,然后重新运行12.3.2节中使用了 TextQuery 的程序。

#ifndef TEXTQUERY_H_
#define TEXTQUERY_H_#include <string>
#include <vector>
#include <map>
#include <fstream>
#include <sstream>
#include <set>
#include <memory>
#include <iostream>
#include <algorithm>
#include <iterator>
#include "StrBlob.h"namespace chapter10
{class TextQuery{public:class QueryResult;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>>> word_map;};class TextQuery::QueryResult{friend std::ostream& print(std::ostream&, const QueryResult&);public:QueryResult(std::string s, std::shared_ptr<std::set<line_no>> p, StrBlob f) : sought(s), lines(p), file(f) { }std::set<StrBlob::size_type>::iterator begin() const { return lines->begin(); }std::set<StrBlob::size_type>::iterator end() const { return lines->end(); }// std::shared_ptr<StrBlob> get_file() const { return std::make_shared<StrBlob>(file); }const StrBlob& get_file() const { return file; }private:std::string sought;std::shared_ptr<std::set<line_no>> lines;StrBlob file;};TextQuery::TextQuery(std::ifstream &ifs){std::string text_line;while(std::getline(ifs, text_line)){file.push_back(text_line);int line_number = file.size() - 1;std::istringstream line(text_line);std::string text_word;while(line >> text_word){std::string word;std::copy_if(text_word.begin(), text_word.end(), std::back_inserter(word), isalpha);// std::cout << word << std::endl;auto &wm_lines = word_map[word];if(!wm_lines)wm_lines.reset(new std::set<line_no>);wm_lines->insert(line_number);}}}TextQuery::QueryResult TextQuery::query(const std::string &sought) const{static std::shared_ptr<std::set<TextQuery::line_no>> nodata(new std::set<TextQuery::line_no>);auto loc = word_map.find(sought);if(loc == word_map.end())return QueryResult(sought, nodata, file);elsereturn QueryResult(sought, loc->second, file);}std::ostream &print(std::ostream &os, const TextQuery::QueryResult &qr){os << qr.sought << " occurs " << qr.lines->size() << " " /*<< make_plural(qr.lines->size(), "time", "s")*/ << std::endl;for(auto num : *qr.lines){ConstStrBlobPtr p(qr.file, num);os << "\t(line " << num + 1 << ") " << p.deref() << std::endl;}return os;}
}#endif

http://www.ppmy.cn/news/98508.html

相关文章

Unity的UnityStats: 属性详解与实用案例

UnityStats 属性详解 UnityStats 是 Unity 引擎提供的一个用于监测游戏性能的工具&#xff0c;它提供了一系列的属性值&#xff0c;可以帮助开发者解游戏的运行情况&#xff0c;从而进行优化。本文将详细介绍 UnityStats 的每个属性值&#xff0c;并提供多个使用例子帮助开发者…

unix环境高级编程 第一章 UNIX基础知识 Go实现代码

ls命令的Go语言实现 package mainimport ("fmt""os" )func main() {if len(os.Args) ! 2 {panic("参数数量不足")}targetPath : os.Args[1]if dirList, err : os.ReadDir(targetPath); err nil {for _, dirInfo : range dirList {fmt.Println(…

六级备考23天|CET-6|翻译技巧4|2013年官方样题|新年|9:45~11:00

目录 1 PRACTICE ANSWER 2 PRACTICE ANSWER 3 ​ PRACTICE ANSWER 4 PRACTICE ANSWER 5 PRACTICE ANSWER 6 ​ PRACTICE ANSWER ​​​​​​​ 答案整合​​​​​​​ 1 PRACTICE Chinese new year is the Chinese most important traditional festival, wh…

R-Meta分析与【文献计量分析、贝叶斯、机器学习等】多技术融合实践与拓展

Meta分析是针对某一科研问题&#xff0c;根据明确的搜索策略、选择筛选文献标准、采用严格的评价方法&#xff0c;对来源不同的研究成果进行收集、合并及定量统计分析的方法&#xff0c;最早出现于“循证医学”&#xff0c;现已广泛应用于农林生态&#xff0c;资源环境等方面。…

sql语句查询数据库字段和表字段数量

》新建数据库:CREATE DATABASE IF NOT EXISTS 数据库名; 示例&#xff1a;:CREATE DATABASE IF NOT EXISTS test_db; 》进入数据库&#xff1a;use 数据库名称&#xff1b; 示例&#xff1a;use test_db; 》数据库中创建表: create table 表名(字段名 字段类型(长度),字段名 字…

Dom解析与Sax解析的区别

1.Dom解析&#xff1a; Dom解析的时候&#xff0c;首先要把整个文件读取完毕&#xff0c;装载到内存中。然后进行解析&#xff0c;在解析的过程中&#xff0c;你可以直接获取某个节点&#xff0c;进行操作&#xff0c;也可以获取根节点然后进行遍历操作&#xff0c;得到所有的…

Linux 系统编程:内存管理系统调用的深度解析

Linux 系统编程&#xff1a;内存管理系统调用的深度解析 一、引言 (Introduction)1.1 Linux 系统编程概述 (Overview of Linux System Programming)1.2 内存管理的重要性 (Importance of Memory Management)1.3 系统调用的作用 (Role of System Calls) 二、Linux 内存管理基础 …

Allegro操作规范

光绘输出操作规范 1.1添加钻孔表 添加钻孔表的具体步骤为: 1.通过屏幕右边的Visibility选项的Views列表,将Drill层打开 2.将Visibility选项中的PIN和Via选项都选中,见下图所示: 1.2添加钻孔文件 参数设好之后关闭NC Drill/Parameters窗口,输出数控机床钻孔文件的命…