3

Given the following program:

#include <vector>
#include <iostream>

using namespace std;

int main()
{
    unsigned n;
    vector<double> xvec;

    cin >> n;
    while (xvec.size() < n)
    {
        double x;
        cin >> x;
        xvec.push_back(x);
    }

    return 0;
}

Is there a way, using STL, to write this without the explicit while loop (e.g., using a copy() algorithm and an inserter?).

I haven't found a way to do this when the number of elements is read at runtime (as in the variable 'n', here).

reddish
  • 1,360
  • 2
  • 12
  • 27
  • 2
    Use [`std::copy_n`](http://en.cppreference.com/w/cpp/algorithm/copy_n). But your code is broken because of the unguarded input, and reading `n` or `x` is generally undefined behaviour. – Kerrek SB Sep 20 '12 at 15:51
  • Thanks. The code is not broken though; I make the conscious choice to accept undefined behavior in case of input errors. – reddish Sep 20 '12 at 16:04
  • 1
    Implement your own `copy_n`? It should be a trivial piece of code, about three lines I'd say. By the way, don't forget to `reserve` your vector's capacity. – Kerrek SB Sep 20 '12 at 16:18
  • 2
    @KerrekSB - But, consider http://stackoverflow.com/questions/5074122/stdistream-iterator-with-copy-n-and-friends before using `std::copy_n` with `std::istream_iterator`. – Robᵩ Sep 20 '12 at 17:09
  • @reddish - +1 for short, complete sample program. See http://SSCCE.ORG/. – Robᵩ Sep 20 '12 at 17:13

1 Answers1

2

Here is one way to copy n doubles into a vector:

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

int main()
{
    unsigned n;
    std::vector<double> xvec;

    std::cin >> n;
    xvec.reserve(n);
    std:generate_n(std::back_inserter(xvec), n,
      []() { double d; std::cin >> d; return d; });

    std::copy(xvec.begin(), xvec.end(),
      std::ostream_iterator<double>(std::cout, " "));

    std::cout << "\n";

    return 0;
}

Note: This alternative using std::copy_n won't work:

std::copy_n(std::istream_iterator<double>(std::cin),
    n,
    std::back_inserter(xvec));

This actually reads n+1 elements but only copies n of them (at least on g++ 4.6.3).


Note 2: Limiting the answer to C++98, here is one possible solution:

double GetD() { double d; std::cin >> d; return d; }
...
std:generate_n(std::back_inserter(xvec), n, GetD);
Robᵩ
  • 163,533
  • 20
  • 239
  • 308