How to extract double from a string stream

While working on my C ++ project, I noticed something strange while playing with objects stringstream

: I cannot extract double

from stringstream

using >>

.

Consider the following example:

#include <string>
#include <sstream>

int main(int argc, const char * argv[]) {

    std::string string("1000 ; 523277527397538 ; 0.183 ; 0.453 ; 0.5 ; 0.5 ; 0.033 ; 0 ; 0 ;");
    std::stringstream stringstream(string);
    int integer;
    char character;
    double doubleprec;
    stringstream >> integer >> character;
    stringstream >> integer >> character;
    stringstream >> doubleprec >> character;
    stringstream >> doubleprec >> character;

    return 0;
}

      

Using my debugger I noticed that the variable integer

takes a value first 1000

and then a value 523277527397538

(as expected), but doubleprec

always takes a value 0

.

Why? Am I missing something about how streams work?

+3


source to share


2 answers


Only the first output of the stream output:

stringstream >> integer >> character;

      

is successful. The other three are unrelated to the fact that your int variable cannot hold a value 523277527397538

. Change it to long long

:



long long integer;

      

When stream fetch fails to pass a number literal 523277527397538

to your variable, then string failbit is set and subsequent calls to fetch the string also fail. A good approach is to use an instruction if

when working with an IO stream:

if (stringstream >> integer >> character){
    // success
}

      

+3


source


A quick demo to strengthen Ron's answer: (C ++ 14)

#include <string>
#include <sstream>
#include <iostream>


int main(int argc, const char * argv[]) {


    std::string string("1000 ; 523277527397538 ; 0.183 ; 0.453 ; 0.5 ; 0.5 ; 0.033 ; 0 ; 0 ;");
    std::stringstream stringstream(string);

    auto okfail = [](auto&& b) {
        if (not b) return std::string("fail");
        return std::string("ok");
    };

    auto read = [&](auto&& var, auto&& f) {
        std::cout << "reading " << var << ". Stream is " << okfail(stringstream) << std::endl;
        f();
        std::cout << "read " << var << ". Stream is " << okfail(stringstream) << std::endl;
    };

    int integer1;
    int integer2;
    char character;
    double doubleprec1, doubleprec2;
    read("integer1", [&] { stringstream >> integer1 >> character; });
    read("integer2", [&] { stringstream >> integer2 >> character; });
    read("doubleprec1", [&] { stringstream >> doubleprec1 >> character; });
    read("doubleprec2", [&] { stringstream >> doubleprec2 >> character; });

    std::cout << integer1<< " " << integer2 << " " << doubleprec1 << " " << doubleprec2 << " " << std::endl;
    return 0;
}

      

Sample output (imac 64-bit):



reading integer1. Stream is ok
read integer1. Stream is ok
reading integer2. Stream is ok
read integer2. Stream is fail
reading doubleprec1. Stream is fail
read doubleprec1. Stream is fail
reading doubleprec2. Stream is fail
read doubleprec2. Stream is fail
1000 2147483647 0 0 

      

now change integer2 to long int:

reading integer1. Stream is ok
read integer1. Stream is ok
reading integer2. Stream is ok
read integer2. Stream is ok
reading doubleprec1. Stream is ok
read doubleprec1. Stream is ok
reading doubleprec2. Stream is ok
read doubleprec2. Stream is ok
1000 523277527397538 0.183 0.453 

      

+2


source







All Articles