0

It started with converting a vector<string> to vector<double>. I use gcc without C++11 so I could not use this approach. After having a look at the algorithm template of transpose I tried to use the template instead, but there is a bug for std::stod used inside the template (for gcc 4.x which results in ‘stod’ is not a member of ‘std’)
So why not write it yourself and I use while-loop with stringstream (expensive?):

int i = 0;
while (svec.begin() != svec.end()) {
    stringstream(*svec.begin())>> dvec[i] ;//svec: strings, dvec: doubles
    //dvec[i] = std::stod(*svec.begin());
    ++svec.begin(); i++;
}

Unfortunately I get: double free or corruption (out): 0x00007f4788000ba0 ***

Community
  • 1
  • 1
droid192
  • 2,011
  • 26
  • 43

3 Answers3

4

I think the issue here is that

++svec.begin();

doesn't work the way you think it does. This doesn't advance forward the beginning of the vector. Instead, it gets a (temporary) iterator to the beginning of the vector, then increments that. As a result, you'll be stuck in an infinite loop. To fix this, use a more traditional "loop over a container" loop either by using a range-based for loop or just counting up the indices.

I also noticed that you're writing into dvec by index. Without seeing the code to initialize dvec, I can't be sure of whether this is safe, since if you didn't already resize the vector this will write off the end and lead to undefined behavior. Even if you did set it up properly, because of the broken loop, my guess is that this eventually writes off the end of the vector and is what directly triggers the issue.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
3

First of all, let's clear up some confusion:

  • std::stod is a C++11 function, so if you do not use C++11, then it is not a "bug" if it cannot be found.
  • You mean std::transform and not transpose, don't you?
  • You may very well use std::transform without C++11 and without std::stod. Unfortunately you don't show the code with which you tried.

So why not write it yourself and I use while-loop with stringstream

Yes, why not?

(expensive?):

Measure it :)

But it's unlikely you'll notice a difference.

    int i = 0;
    while (svec.begin() != svec.end()) {

The loop condition does not make sense. begin() and end() do not change. This line effectively reads as "do this stuff as long as the vector does not become empty".

    stringstream(*svec.begin())>> dvec[i] ;//svec: strings, dvec: doubles
    //dvec[i] = std::stod(*svec.begin());
    ++svec.begin(); i++;
    }

I'd say you are overthinking this. The crash you get may come from the fact that you access dvec[i] while dvec is still empty, and you never actually add elements to it. That's undefined behaviour.

It's really as simple as "loop through string vector, use a stringstream on each element to get a double value, and add that value to the result vector", expressed in C++03 as:

// loop through string vector
for (std::vector<std::string>::const_iterator iter = svec.begin(); iter != svec.end(); ++iter)
{
    std::string const& element = *iter;

    // use a stringstream to get a double value:
    std::istringstream is(element);
    double result;
    is >> result;

    // add the double value to the result vector:
    dvec.push_back(result);
}
Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
  • Wow..ok. I guess standard loop is the better way. So [istringstream](http://stackoverflow.com/questions/3292107/whats-the-difference-between-istringstream-ostringstream-and-stringstream-w) and push_back helps avoiding silly mistakes. Is this ok: ` std::istringstream is( *iter );` or why seperate dec/init. of element? – droid192 Feb 15 '16 at 21:37
  • 1
    @Julianemailde: Yes, it's OK. I just wanted my code to be a bit easier to understand. – Christian Hackl Feb 15 '16 at 21:39
0

If you don't have stod (which was added in C++11) you can use strtod and apply it to a C-string that corresponds to the C++ string that you have. Copying from the approach that you linked to and making that change (and cleaning up the formatting):

std::vector<double> convertStringVectortoDoubleVector(
    const std::vector<std::string>& stringVector){
        std::vector<double> doubleVector(stringVector.size());
        std::transform(stringVector.begin(), stringVector.end(), 
            doubleVector.begin(), [](const std::string& val)
                {
                    return strtod(val.c_str(), 0);
                });
        return doubleVector;
}

Note that if the code hasn't already ensured that each string holds a valid representation of a floating-point value you'll have to add code to check whether strtod succeeded.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165