Acceierated C++ 习题解答 第8章
2014-03-12 20:25
183 查看
部分习题参考了网上已有解答,以后会继续完善未解答的习题
EX.8-2
8_2.h
8_2.cpp
EX.8-4
EX.8-6
两种情况都编译失败
考虑另一种情况
两个std::map,一个是 A,一个是B,A、B里面都有元素,怎么把 A里面的元素都赋值给B。 如果使用
std::copy(A.begin(),A.end(),std::back_inserter(B));
编译失败,查看 c++标准库的原始代码,发现 back_inserter里面构造的对象
std::back_insert_iterator里面的 operator=()是这么写的
这样就要求传入的容器必须有push_back()方法,但是 std::map没有提供这类方法,故编译失败。模仿标准库的实现,可以改写方法,实现了
std::copy对 std::map
的使用。
EX.8-7
max函数的两个参数的类型必须能够精确匹配,如果两个类型不匹配则无法通过编译。若max函数使用两个模板参数,当传递两个不同类型的参数(比如int类型和double类型),那么系统环境将无法推断出应该哪个参数转化为另外一个参数的类型。
EX.8-8
mid =(begin+end)/2这样的写法粗看没什么不妥,但是在一些极端情况下,会由于求和中间结果的溢出而导致出现错误(假设这是个32位程序,32位有符号整数可以表示的范围是,如果begin+end的值恰好超过了,那么就会造成上溢出,导致mid变成负数)。所以我们最好把它写成mid=begin+( end-begin)/2。
EX.8-2
8_2.h
#pragma once #include <algorithm> #include <iterator> // 返回一个布尔类型的值,表示两个序列中的元素是否相等,第一个序列由输入迭代器b和e界定, // 第二个序列是从输入迭代器b2指向的元素开始的与第一个序列等长的序列 template <classInputIterator1,class InputIterator2> bool my_equal(InputIterator1 b, InputIterator1 e,InputIterator2 b2) { for ( ;b != e; ++b) { if (*b != *b2) returnfalse; ++b2; } return true; } // 在由正向迭代器b和e界定的序列中,查找由正向迭代器b2和e2界定的子序列,然后返回指向第一个匹配的子序列首元素的正向迭代器 template <classForwardIterator1,class ForwardIterator2> ForwardIterator1 my_search(ForwardIterator1 b,ForwardIterator1 e, ForwardIterator2 b2, ForwardIterator2 e2) { for ( ;b != e; ++b) if(my_equal(b2, e2, b)) return b; return e; } // 返回一个迭代器,指向一个序列中首次出现t值的元素,该序列由输入迭代器b和e界定 template <class InputIterator,class Type> InputIterator my_find(InputIterator b, InputIterator e, const Type& t) { for ( ;b != e; ++b) if (*b == t) return b; return e; } // 返回一个迭代器,指向一个序列中首次满足p表达式的元素,该序列由输入迭代器b和e界定 template <class InputIterator,class Predicate> InputIterator my_find_if(InputIterator b, InputIterator e,Predicate p) { for ( ;b !=e; ++b) if (p(*b)) return b; return e; } // 将由输出迭代器b和e界定的序列中的值复制到目标容器中,目标容器有输出迭代器d指定 // 该函数假定在目标容器中有足够的空间存储复制过来的值,返回一个值指向目标容器末元素后面一个元素 template <class InputIterator,class OutputIterator> OutputIterator my_copy(InputIterator b, InputIterator e,OutputIterator d) { for ( ;b != e; ++b) *d++ = *b; return d; } // 排列容器以使在区间[b, e)中不等于t的元素位于这个域的头部 template <classForwardIterator,class Type> ForwardIterator my_remove(ForwardIterator b, ForwardIteratore, const Type& t) { ForwardIteratorfirst_fail = b; for ( ;b != e; ++b) if (*b != t) *first_fail++ = *b; return first_fail; } // 将与t不匹配的元素复制到由输出迭代器d指向的目标容器中 template <class InputIterator,class OutputIterator,classType> OutputIterator my_remove_copy(InputIterator b, InputIteratore, OutputIterator d,const Type& t) { for ( ;b != e; ++b) if (*b != t) *d++ = *b; return d; } // 将是条件p为假的元素复制到由输出迭代器d指向的目标容器中 template <class InputIterator,class OutputIterator,classPredicate> OutputIterator my_remove_copy_if(InputIterator b,InputIterator e, OutputIterator d, Predicate p) { for ( ;b != e; ++b) if (!p(*b)) *d++ = *b; return d; } // 根据[b, e)中的元素运行函数f,将f的结果存储在d中 template <class InputIterator,class OutputIterator,classFunction> OutputIterator my_transform(InputIterator b, InputIterator e,OutputIterator d, Function f) { for ( ;b != e; ++b) *d++ = f(*b); return d; } // 将由双向迭代器b和e界定的序列分成两部分,会将满足表达式p为真的元素放在容器的前面,不满足p为真的元素放在容器的后面。 // 返回第一个不满足p为真的元素的迭代器,如果对于所有元素都满足p为真,则返回e // 另一个函数stable_partition,是两部分中的元素都保持原来在容器中的先后顺序 template <classForwardIterator,class Predicate> ForwardIterator my_partition(ForwardIterator b,ForwardIterator e, Predicate p) { ForwardIteratorfirst_fail = b; for ( ;b != e; ++b) if (p(*b)) swap(*first_fail++, *b); return first_fail; } template <class InputIterator,class Type> Type my_accumulate(InputIterator b, InputIterator e, Type t){ for ( ;b != e; ++b) t += *b; return t; }
8_2.cpp
#include <iostream> #include <string> #include <conio.h> #include "8_2.h" using namespace std; char transformString(char c){ return ++c; } bool passes(char c) { return c == 'P'; } int main() { string trans = "abc"; my_transform(trans.begin(),trans.end(), trans.begin(), transformString); cout << trans<< endl; string grades = "PPFFPFP"; my_partition(grades.begin(),grades.end(), passes); cout << grades<< endl; getch(); return 0; }
EX.8-4
#include <iostream> #include <string> #include <conio.h> using namespace std; template<class Type> void my_swap(Type &a, Type &b) { Type temp = a; a = b; b = temp; } template<class Bi> void reverse(Bi begin, Bi end) { Bi temp; while (begin != end) { --end; if (begin != end) my_swap(*begin++,*end); } } int main() { string str = "kindle"; reverse(str.begin(),str.end()); cout << str<< endl; getch(); return 0; }
EX.8-6
两种情况都编译失败
考虑另一种情况
两个std::map,一个是 A,一个是B,A、B里面都有元素,怎么把 A里面的元素都赋值给B。 如果使用
std::copy(A.begin(),A.end(),std::back_inserter(B));
编译失败,查看 c++标准库的原始代码,发现 back_inserter里面构造的对象
// TEMPLATE FUNCTION back_inserter template<class _Container>inline back_insert_iterator<_Container>back_inserter(_Container& _Cont) { // return a back_insert_iterator return (std::back_insert_iterator<_Container>(_Cont)); }
std::back_insert_iterator里面的 operator=()是这么写的
back_insert_iterator<_Container>& operator=( typename _Container::const_reference _Val) { // push value into container container->push_back(_Val); return (*this); }
这样就要求传入的容器必须有push_back()方法,但是 std::map没有提供这类方法,故编译失败。模仿标准库的实现,可以改写方法,实现了
std::copy对 std::map
的使用。
EX.8-7
max函数的两个参数的类型必须能够精确匹配,如果两个类型不匹配则无法通过编译。若max函数使用两个模板参数,当传递两个不同类型的参数(比如int类型和double类型),那么系统环境将无法推断出应该哪个参数转化为另外一个参数的类型。
EX.8-8
mid =(begin+end)/2这样的写法粗看没什么不妥,但是在一些极端情况下,会由于求和中间结果的溢出而导致出现错误(假设这是个32位程序,32位有符号整数可以表示的范围是,如果begin+end的值恰好超过了,那么就会造成上溢出,导致mid变成负数)。所以我们最好把它写成mid=begin+( end-begin)/2。
相关文章推荐
- Introdution to 3D Game Programming With DirectX11 第8章 习题解答
- 陶哲轩实分析 附录 A 习题解答
- 《快学Scala》第三章习题解答
- 《学习OpenCV》课后习题解答8
- [PeterDLax著泛函分析习题参考解答]第2章 线性映射
- leetcode习题解答:32. Longest Valid Parentheses
- [詹兴致矩阵论习题参考解答]习题1.13
- [詹兴致矩阵论习题参考解答]习题3.4
- [詹兴致矩阵论习题参考解答]习题4.11
- [詹兴致矩阵论习题参考解答]习题6.7
- [詹兴致矩阵论习题参考解答]习题7.6
- 深入理解计算机系统第二版习题解答CSAPP 2.2
- 算法导论(3版)第5章少量习题的解答
- 算法艺术与信息学竞赛——习题解答
- python教程11--《基本数据结构习题及其解答》
- 随机排列算法及《算法导论》5.3节习题解答
- [偏微分方程教程习题参考解答]2.2线性齐次偏微分方程
- erlang基础练习-编程指南习题部分解答
- C++ Primer 笔记+习题解答(十)
- TCP/IP详解卷1:协议第三章课后习题解答