If I have the string "2.5 4.2 6.9 1.1", how can I convert that into a vector of doubles as efficiently as possible?
Asked
Active
Viewed 219 times
3 Answers
4
vector<double> convert_string_to_vec(std::string const & str)
{
std::istringstream input{str};
vector<double> output{std::istream_iterator<double>{input},
std::istream_iterator<double>{}};
return output;
}
You'll need to include <sstream>
as well as <iterator>
for this to work. Here's a working example.

AliciaBytes
- 7,300
- 6
- 36
- 47
-
2You need to either use universal initialization, `{}`, or stuff one of those iterators (ideally the first) in a nested set of parens, or you code will hit an [MVP](http://en.wikipedia.org/wiki/Most_vexing_parse). And minor: your decl is missing a semi-colon. – WhozCraig Nov 13 '13 at 00:48
-
Got to hate that mvp... Changed them all to universal initialization and added link to coliru example. thanks craig =) – AliciaBytes Nov 13 '13 at 00:54
-
Be happy we have UI now. Before with all the parens I kept having Lisp flashbacks from college. – WhozCraig Nov 13 '13 at 00:55
-
1You can always use named iterators, which you can declare in the same statement, avoiding mvp *and* saving you from having to tediously type `std::istream_iterator
` twice. http://coliru.stacked-crooked.com/a/dca982f0429e3595 – Benjamin Lindley Nov 13 '13 at 01:18 -
This creates a vector and then returns a copy of that vector, so it could be made more efficient. – snips-n-snails Nov 13 '13 at 01:22
-
1@traal: In a world with [RVO](http://en.wikipedia.org/wiki/Return_value_optimization) and [move semantics](http://en.wikipedia.org/wiki/Move_semantics#Rvalue_references_and_move_constructors), no, it really can't. At least, not in that respect. There may be optimization opportunities in the string-to-double conversion though. – Benjamin Lindley Nov 13 '13 at 01:24
-
@traal like Benjamin said already, there shouldn't be a copy at all. And moving is insignificant compared to the `stringstream` performance. – AliciaBytes Nov 13 '13 at 01:32
0
This is how I would generally do it. Possibly not the most efficient way, but very simple.
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main()
{
std::string d("2.5 4.2 6.9 1.1");
std::stringstream s(d);
std::vector<double> result;
double temp;
while(s >> temp)
{
result.push_back(temp);
}
for(size_t i = 0; i < result.size(); ++i)
{
std::cout << result[i] << "\n";
}
return 0;
}

Retired Ninja
- 4,785
- 3
- 25
- 35
-
is there a specific reason for not using `std::endl` but rather using `"\n"` ? – Varaquilex Nov 13 '13 at 00:52
-
1@Volkanİlbeyli `std::endl` flushes the stream as well as inserting a new line. There's no need to flush after each iteration so `'\n'` is preferred in this case. – David G Nov 13 '13 at 00:53
-
Yeah, the `"\n"` is to avoid extra flushing of the stream. Admittedly not all that important in a small example like this, but I'm trying to teach myself to prefer it for when there is a difference. – Retired Ninja Nov 13 '13 at 00:58
0
Here's a unique way:
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
template <class Facet>
struct erasable_facet : Facet
{
erasable_facet() : Facet(0) { }
~erasable_facet() { }
};
std::vector<double> convert(const std::string& str)
{
using num_get = std::num_get<char>;
erasable_facet<num_get> facet;
std::stringbuf buf(str);
std::vector<double> v;
std::ios ios(nullptr);
std::ios_base::iostate err = std::ios_base::goodbit;
double d;
std::istreambuf_iterator<char> it, end;
do
{
it = facet.get(&buf, end, ios, err, d);
buf.sbumpc(); // skip space
if (!(err & std::ios_base::failbit) &&
!(err & std::ios_base::badbit))
v.push_back(d);
else
return v;
} while (it != end);
return v;
}
int main()
{
std::string str = "1.24 5.32 9.53";
auto v = convert(str);
}

David G
- 94,763
- 41
- 167
- 253