Как извлечь double из stringstream
Работая над моим проектом C++, я заметил кое-что странное, играя с объектами stringstream
: я не могу извлечь double
из stringstream
с помощью >>
.
Рассмотрим следующий пример:
#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;
}
Используя мой отладчик, я заметил, что переменная integer
сначала принимает значение 1000
, а затем значение 523277527397538
(Как я и ожидал), но doubleprec
всегда принимает значение 0
.
Почему это? Я что-то упускаю из виду в том, как работают потоки?
2 ответа:
Только первый оператор вывода потока:
stringstream >> integer >> character;
Успешно. Остальные три не связаны с тем, что ваша переменная int не может содержать значение
523277527397538
. Измените его наlong long
:long long integer;
Если при извлечении потока не удается поместить числовой литерал
523277527397538
в переменную, то устанавливается failbit stringstream, и последующие вызовы извлечения stringstream также завершаются неудачей. Хорошим подходом является использование оператораif
при работе с потоком IO:if (stringstream >> integer >> character){ // success }
Быстрая демонстрация, чтобы усилить ответ Рона: (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; }
Пример вывода (imac 64-разрядный):
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
Теперь измените integer2 на 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