IE盒子

搜索
查看: 138|回复: 0

c++ STL生成算法:generate()、generate_n()详解

[复制链接]

1

主题

2

帖子

3

积分

新手上路

Rank: 1

积分
3
发表于 2023-1-12 17:48:36 | 显示全部楼层 |阅读模式

主要函数有:

  • generate():用一操作的结果填充所有元素。
  • generate_n():用一操作的结果填充前n个元素。
generate函数模板的行为等效于:

template <class ForwardIterator, class Generator>
  void generate ( ForwardIterator first, ForwardIterator last, Generator gen )
{
  while (first != last) {
    *first = gen();
    ++first;
  }
}可以发现,它的前两个参数是指定范围的正向迭代器,第三个参数是用来定义无参函数对象;这与for_each()算法是不同的,for_each()算法将一个函数对象应用到序列中的每一个元素上。函数对象的参数是for_each()的前两个参数所指定序列中元素的引用,因此它可以直接修改被保存的值。所以generate()算法的功能是填充而非修改。
例子:
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
using namespace std;
class Fibonacci{
    int f1;
    int f2;
public:
    Fibonacci(int start1, int start2){
        f1 = start1;
        f2 = start2;
    }
    int operator()(){
        int r = f1 + f2;
        f1 = f2;
        f2 = r;
        return r;
    }
};
int main(){
    vector<int> v1(10);
    generate(v1.begin(), v1.end(), Fibonacci(0, 1));
    cout<< "0, 1开始前10个斐波那契数列为: " << endl;
    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " "));
    return 0;
}

Fibonacci(0,1)调用构造函数一方面重新生成了新的Fibonacci 对象,一方面又重新给斐波那契数列初值fl,f2重新赋值。利用函数对象可以封装许多初始化信息、隐蔽性、封装性更好。
generate_n函数模板的行为等效于:

template <class OutputIterator, class Size, class Generator>
  void generate_n ( OutputIterator first, Size n, Generator gen )
{
  while (n>0) {
    *first = gen();
    ++first; --n;
  }
}与generate函数类似,第一个参数仍然是序列的开始迭代器,第二个参数是由第三个参数设置的元素的个数。为了避免程序崩溃,这个序列必须至少有第二个参数定义的元素个数。
接下来,按要求写代码: 生成随机数。要求产生10个[0,100]间整型数,产生10个[0,1)间小数。
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <time.h>
using namespace std;
template<class T>
class MyRandom{
   
};
template<>
class MyRandom<int>{
    public:
        MyRandom(){
            srand(time(NULL));
        }
        int operator()(){
            int result = rand() % 100;
            return result;
        }
};
template<>
class MyRandom<float>{
    public:
        MyRandom(){
            srand(time(NULL));
        }
        float operator()(){
            float result = rand() % 100 * 0.01f;
            return result;
        }
};
int main(){
    cout<< "产生[0, 100)间10个整型随机数为: " << endl;
    vector<int> v1(10);
    generate_n(v1.begin(), 10, MyRandom<int>());
    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " "));
    cout<< endl;
   
    cout<< "产生[0, 100)间10个浮点随机数为: " << endl;
    vector<float> v2(10);
    generate_n(v2.begin(), 10, MyRandom<float>());
    copy(v2.begin(), v2.end(), ostream_iterator<float>(cout, " "));
    return 0;
}

首先为了确保产生随机数最好每次起始“种子”都不同, 我们采用“时间函数”做随机数种子。即在特化类构造函数中都执行了srand ( time (NULL)),这样每次产生新的MyRandom函数对象时,由于时间的不同,也就决定了每次产生的随机数种子不同,进而决定产生的随机数序列不同。
然后在随机数泛型类 MyRandom的基础上构建两个特化类 MyRandom及 MyRandom。很明显它们的接口形式是相同的。如果需要增加新数据类型的随机数,只须增加一个相应的模板特化类就可以了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表