120 votes

utiliser std::fill pour remplir le vecteur avec des nombres croissants

Je voudrais remplir un vector<int> en utilisant std::fill mais au lieu d'une valeur, le vecteur doit contenir des nombres en ordre croissant après.

J'ai essayé d'y parvenir en itérant le troisième paramètre de la fonction par un, mais cela ne me donnait que des vecteurs remplis de 1 ou de 2 (en fonction de la position de l'argument de la fonction). ++ opérateur).

Ejemplo:

vector<int> ivec;
int i = 0;
std::fill(ivec.begin(), ivec.end(), i++); // elements are set to 1
std::fill(ivec.begin(), ivec.end(), ++i); // elements are set to 2

5voto

Frerich Raabe Points 23711

Si vous préférez ne pas utiliser les fonctionnalités de C++11, vous pouvez utiliser std::generate :

#include <algorithm>
#include <iostream>
#include <vector>

struct Generator {
    Generator() : m_value( 0 ) { }
    int operator()() { return m_value++; }
    int m_value;
};

int main()
{
    std::vector<int> ivec( 10 );

    std::generate( ivec.begin(), ivec.end(), Generator() );

    std::vector<int>::const_iterator it, end = ivec.end();
    for ( it = ivec.begin(); it != end; ++it ) {
        std::cout << *it << std::endl;
    }
}

Ce programme imprime de 0 à 9.

5voto

pururu Points 49

Std::iota est limité à une séquence n, n+1, n+2, ...

Mais que faire si l'on veut remplir un tableau avec une séquence générique f(0), f(1), f(2), etc. Souvent, nous pouvons éviter un générateur de suivi d'état. Par exemple,

int a[7];
auto f = [](int x) { return x*x; };
transform(a, a+7, a, [a, f](int &x) {return f(&x - a);});

produira la séquence de carrés

0 1 4 9 16 25 36

Toutefois, cette astuce ne fonctionnera pas avec d'autres conteneurs.

Si vous êtes coincé avec C++98, vous pouvez faire des choses horribles comme :

int f(int &x) { int y = (int) (long) &x / sizeof(int); return y*y; }

et ensuite

int a[7];
transform((int *) 0, ((int *) 0) + 7, a, f);

Mais je ne le recommande pas. :)

4voto

Egor Wexler Points 538

Il existe une autre option - sans utiliser de iota. On peut utiliser l'expression For_each + lambda :

vector<int> ivec(10); // the vector of size 10
int i = 0;            // incrementor
for_each(ivec.begin(), ivec.end(), [&](int& item) { ++i; item += i;});

Deux choses importantes qui expliquent pourquoi ça marche :

  1. Lambda capture la portée externe [&] ce qui signifie que i sera disponible dans l'expression.
  2. passé comme une référence, il est donc mutable à l'intérieur du vecteur.

2voto

No Idea For Name Points 10466

Cela fonctionne aussi

j=0;
for(std::vector<int>::iterator it = myvector.begin() ; it != myvector.end(); ++it){
    *it = j++;
}

2voto

Mikhail Points 6770

En parlant de coup de pouce :

auto ivec = boost::copy_range<std::vector<int>>(boost::irange(5, 10));

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X