C++编程思想 第2卷 第6章 通用算法 函数对象 可更多的函数对象例子

对多数内建的基本函数对象模板提供了简单的测试
用这种方式如何使用每个模板
并取得相应的操作结果

//: C06:Generators.h
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// Different ways to fill sequences.
#ifndef GENERATORS_H
#define GENERATORS_H
#include <cstring>
#include <set>
#include <cstdlib>

// A generator that can skip over numbers:
class SkipGen {
  int i;
  int skp;
public:
  SkipGen(int start = 0, int skip = 1)
  : i(start), skp(skip) {}
  int operator()() {
    int r = i;
    i += skp;
    return r;
  }
};

// Generate unique random numbers from 0 to mod:
class URandGen {
  std::set<int> used;
  int limit;
public:
  URandGen(int lim) : limit(lim) {}
  int operator()() {
    while(true) {
      int i = int(std::rand()) % limit;
      if(used.find(i) == used.end()) {
        used.insert(i);
        return i;
      }
    }
  }
};

// Produces random characters:
class CharGen {
  static const char* source;
  static const int len;
public:
  char operator()() {
    return source[std::rand() % len];
  }
};
#endif // GENERATORS_H ///:~

 

//: C06:Generators.cpp {O}
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
#include "Generators.h"
const char* CharGen::source = "ABCDEFGHIJK"
  "LMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const int CharGen::len = std::strlen(source);
///:~


SkipGen函数对象 返回一个算术序列当前元素的下一个数
共同的差值保存在数据成员skp中CharGen对象返回一个随机的字母表中的字符

//: C06:FunctionObjects.cpp {-bor}
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// Illustrates selected predefined function object
// templates from the Standard C++ library.
//{L} Generators
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <iostream>
#include <iterator>
#include <vector>
#include "Generators.h"
#include "PrintSequence.h"
using namespace std;

template<typename Contain, typename UnaryFunc>
void testUnary(Contain& source, Contain& dest,
  UnaryFunc f) {
  transform(source.begin(), source.end(), dest.begin(), f);
}

template<typename Contain1, typename Contain2,
  typename BinaryFunc>
void testBinary(Contain1& src1, Contain1& src2,
  Contain2& dest, BinaryFunc f) {
  transform(src1.begin(), src1.end(),
    src2.begin(), dest.begin(), f);
}

// Executes the expression, then stringizes the
// expression into the print statement:
#define T(EXPR) EXPR; print(r.begin(), r.end(), \
  "After " #EXPR);
// For Boolean tests:
#define B(EXPR) EXPR; print(br.begin(), br.end(), \
  "After " #EXPR);

// Boolean random generator:
struct BRand {
  bool operator()() { return rand() % 2 == 0; }
};

int main() {
  const int SZ = 10;
  const int MAX = 50;
  vector<int> x(SZ), y(SZ), r(SZ);
  // An integer random number generator:
  URandGen urg(MAX);
  srand(time(0));  // Randomize
  generate_n(x.begin(), SZ, urg);
  generate_n(y.begin(), SZ, urg);
  // Add one to each to guarantee nonzero divide:
  transform(y.begin(), y.end(), y.begin(),
    bind2nd(plus<int>(), 1));
  // Guarantee one pair of elements is ==:
  x[0] = y[0];
  print(x.begin(), x.end(), "x");
  print(y.begin(), y.end(), "y");
  // Operate on each element pair of x & y,
  // putting the result into r:
  T(testBinary(x, y, r, plus<int>()));
  T(testBinary(x, y, r, minus<int>()));
  T(testBinary(x, y, r, multiplies<int>()));
  T(testBinary(x, y, r, divides<int>()));
  T(testBinary(x, y, r, modulus<int>()));
  T(testUnary(x, r, negate<int>()));
  vector<bool> br(SZ); // For Boolean results
  B(testBinary(x, y, br, equal_to<int>()));
  B(testBinary(x, y, br, not_equal_to<int>()));
  B(testBinary(x, y, br, greater<int>()));
  B(testBinary(x, y, br, less<int>()));
  B(testBinary(x, y, br, greater_equal<int>()));
  B(testBinary(x, y, br, less_equal<int>()));
  B(testBinary(x, y, br, not2(greater_equal<int>())));
  B(testBinary(x,y,br,not2(less_equal<int>())));
  vector<bool> b1(SZ), b2(SZ);
  generate_n(b1.begin(), SZ, BRand());
  generate_n(b2.begin(), SZ, BRand());
  print(b1.begin(), b1.end(), "b1");
  print(b2.begin(), b2.end(), "b2");
  B(testBinary(b1, b2, br, logical_and<int>()));
  B(testBinary(b1, b2, br, logical_or<int>()));
  B(testUnary(b1, br, logical_not<int>()));
  B(testUnary(b1, br, not1(logical_not<int>())));
  getchar();
} ///:~


使用了一个简单的函数模板print()
它能够打印任意类型的序列并且可以附加可选择的信息

testUnary()函数有一个源 vector
一个目的vector和一个用在源vector上来产生目的vector的一元函数对象

贴剩下的代码

//: C06:PrintSequence.h
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// Prints the contents of any sequence.
#ifndef PRINTSEQUENCE_H
#define PRINTSEQUENCE_H
#include <algorithm>
#include <iostream>
#include <iterator>

template<typename Iter>
void print(Iter first, Iter last, const char* nm = "",
           const char* sep = "\n",
           std::ostream& os = std::cout) {
  if(nm != 0 && *nm != '\0')
    os << nm << ": " << sep;
  typedef typename 
    std::iterator_traits<Iter>::value_type T;
  std::copy(first, last, 
            std::ostream_iterator<T>(std::cout, sep));
  os << std::endl;
}
#endif // PRINTSEQUENCE_H ///:~


输出
x:
9
36
34
37
18
44
0
33
20
4

y:
9
28
17
22
5
48
46
34
19
32

After testBinary(x, y, r, plus<int>()):
18
64
51
59
23
92
46
67
39
36

After testBinary(x, y, r, minus<int>()):
0
8
17
15
13
-4
-46
-1
1
-28

After testBinary(x, y, r, multiplies<int>()):
81
1008
578
814
90
2112
0
1122
380
128

After testBinary(x, y, r, divides<int>()):
1
1
2
1
3
0
0
0
1
0

After testBinary(x, y, r, modulus<int>()):
0
8
0
15
3
44
0
33
1
4

After testUnary(x, r, negate<int>()):
-9
-36
-34
-37
-18
-44
0
-33
-20
-4

After testBinary(x, y, br, equal_to<int>()):
1
0
0
0
0
0
0
0
0
0

After testBinary(x, y, br, not_equal_to<int>()):
0
1
1
1
1
1
1
1
1
1

After testBinary(x, y, br, greater<int>()):
0
1
1
1
1
0
0
0
1
0

After testBinary(x, y, br, less<int>()):
0
0
0
0
0
1
1
1
0
1

After testBinary(x, y, br, greater_equal<int>()):
1
1
1
1
1
0
0
0
1
0

After testBinary(x, y, br, less_equal<int>()):
1
0
0
0
0
1
1
1
0
1

After testBinary(x, y, br, not2(greater_equal<int>())):
0
0
0
0
0
1
1
1
0
1

After testBinary(x,y,br,not2(less_equal<int>())):
0
1
1
1
1
0
0
0
1
0

b1:
0
0
1
0
0
0
0
1
0
1

b2:
0
1
1
1
1
1
0
1
1
0

After testBinary(b1, b2, br, logical_and<int>()):
0
0
1
0
0
0
0
1
0
0

After testBinary(b1, b2, br, logical_or<int>()):
0
1
1
1
1
1
0
1
1
1

After testUnary(b1, br, logical_not<int>()):
1
1
0
1
1
1
1
0
1
0

After testUnary(b1, br, not1(logical_not<int>())):
0
0
1
0
0
0
0
1
0
1
T()测试产生数字型值的每一个函数对象
B()测试产生布尔型结果的每一个函数对象

在输出结果中想使布尔型值显示为 真 和 假 而不是 1和0
则要调用cout.set(ios::boolalpha)

一个绑定程序无需产生一元判断函数
它能创建任意的一元函数

//: C06:FBinder.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// Binders aren't limited to producing predicates.
//{L} Generators
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <iostream>
#include <iterator>
#include <vector>
#include "Generators.h"
using namespace std;

int main() {
  ostream_iterator<int> out(cout," ");
  vector<int> v(15);
  srand(time(0));  // Randomize
  generate(v.begin(), v.end(), URandGen(20));
  copy(v.begin(), v.end(), out);
  transform(v.begin(), v.end(), v.begin(),
            bind2nd(multiplies<int>(), 10));
  copy(v.begin(), v.end(), out);
  getchar();
} ///:~

输出 这个还要Generators.h Generators.cpp
2 14 10 7 15 11 4 1 19 0 16 9 13 6 8 20 140 100 70 150 110 40 10 190 0 160 90 130 60 80
因为transform()的第3个参数与第1个参数一样
所以结果元素又被复制回源vector
绑定程序 绑定 的参数不能死一个函数对象 
但也无需是一个编译时常量

//: C06:BinderValue.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// The bound argument can vary.
#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <cstdlib>
using namespace std;

int boundedRand() { return rand() % 100; }

int main() {
  const int SZ = 20;
  int a[SZ], b[SZ] = {0};
  generate(a, a + SZ, boundedRand);
  int val = boundedRand();
  int* end = remove_copy_if(a, a + SZ, b,
                            bind2nd(greater<int>(), val));
  // Sort for easier viewing:
  sort(a, a + SZ);
  sort(b, end);
  ostream_iterator<int> out(cout, " ");
  cout << "Original Sequence:" << endl;
  copy(a, a + SZ, out); cout << endl;
  cout << "Values <= " << val << endl;
  copy(b, end, out); cout << endl;
  getchar();
} ///:~

输出 随机数 
Original Sequence:
0 5 24 27 27 34 36 41 42 45 58 61 62 64 67 69 78 81 91 95
Values <= 91
0 5 24 27 27 34 36 41 42 45 58 61 62 64 67 69 78 81 91

这里用20个在0到100之间的随机数填充一个数组
当然用户可以在命令行提供一个值
用来限制产生随机数的范围
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值