Acceierated C++ 习题解答 第8章

来源:互联网 发布:淘宝买快排被查 编辑:程序博客网 时间:2024/05/21 17:43

部分习题参考了网上已有解答,以后会继续完善未解答的习题


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,一个是BAB里面都有元素,怎么把 A里面的元素都赋值给B 如果使用

std::copy(A.begin(),A.end(),std::back_inserter(B));

编译失败,查看 c++标准库的原始代码,发现 back_inserter里面构造的对象

// TEMPLATE FUNCTION back_insertertemplate<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。

 


0 0
原创粉丝点击