5

I have a string like:

string line="6,148,72,35,0,33.6,0.627,50,1";

and I would like to copy the numbers within it to the respective elements of a std::vector. I would like to use std::vector.assign() or std::copy().

So I wrote:

string line="6,148,72,35,0,33.6,0.627,50,1";
vector<double> row;
istringstream iss { line };
row.assign(istream_iterator<double>(iss), istream_iterator<double>());

but the result is that assign() only copies the first number from the string to the vector, i.e. I get

row={6}

while I would like to get

row={6,148,72,35,0,33.6,0.627,50,1}

Same thing if I use std::copy instead, like in:

string line="6,148,72,35,0,33.6,0.627,50,1";
vector<double> row;
istringstream iss { line };
copy(istream_iterator<double>(iss), istream_iterator<double>(), back_inserter(row));

It looks like copy from the string ends after reading the first number, and I don't know why. Any idea how to use assign() or copy() to copy every number from the string into the vector?

Fanta
  • 2,825
  • 5
  • 26
  • 35
  • 3
    `std::replace(line.begin(), line.end(), ',', ' ');` before defining `iss`, like [here](http://coliru.stacked-crooked.com/a/013c459db27390b5) – Piotr Skotnicki Jan 29 '15 at 16:35
  • @PiotrS. Right on the spot. Now I'm wondering, is there a way to avoid the replacement? Something like defining the separtion character to `,`? – Adri C.S. Jan 29 '15 at 16:54
  • 1
    @AdriC.S. Yes! There is, however in your case I believe the replace is preferable: http://stackoverflow.com/a/28197337/2642059 – Jonathan Mee Jan 29 '15 at 16:56
  • 2
    @AdriC.S. Yup, if setting up `istream`s to read in CSVs is something you have to do a lot, you could make a `const ctype::mask` and just use that wherever. But if it's just this one place I'd side with `replace` cause lets be honest, using `ctype::mask` is something no one does so it will make your code difficult to understand. – Jonathan Mee Jan 29 '15 at 17:03

1 Answers1

5

If you get your string right you can do this all in one line with Visual Studio 2013:

string line="6,148,72,35,0,33.6,0.627,50,1";

std::replace(line.begin(), line.end(), ',', ' ');

vector<double> row{istream_iterator<double>(istringstream(line)), istream_iterator<double>()};

Note that gcc has a bug with moving an istream so you'll have to do this on gcc:

string line="6,148,72,35,0,33.6,0.627,50,1";

std::replace(line.begin(), line.end(), ',', ' ');

istringstream bar(line);

vector<double> foo{istream_iterator<double>(bar), istream_iterator<double>()};

Thankfully the bug is already fixed in gcc 5, so we're almost there.

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288