std:: строка с плавающей или двойной
Я пытаюсь преобразовать std::string
to float/double
.
Я попробовал:
std::string num = "0.6";
double temp = (double)atof(num.c_str());
но он всегда возвращает ноль. Есть другие способы?
15 ответов:
std::string num = "0.6"; double temp = ::atof(num.c_str());
делает это для меня, это допустимый синтаксис C++ для преобразования строки в double.
вы можете сделать это с помощью stringstream или boost::lexical_cast, но они имеют штраф за производительность.
Ахаха, у вас есть проект Qt ...
QString winOpacity("0.6"); double temp = winOpacity.toDouble();
дополнительное Примечание:
Если входные данные-этоconst char*
,QByteArray::toDouble
будет быстрее.
стандартная библиотека (C++11) предлагает необходимую функциональность с
std::stod
:std::string s = "0.6" std::wstring ws = "0.7" double d = std::stod(s); double dw = std::stod(ws);
Я думаю, что стандартная библиотека преобразует внутренне тоже, но таким образом делает код чище. Как правило, для большинства других основных типов, см.
<string>
. Есть некоторые новые функции для строк C, тоже. Смотрите<stdlib.h>
лексический бросок очень хороший.
#include <boost/lexical_cast.hpp> #include <iostream> #include <string> using std::endl; using std::cout; using std::string; using boost::lexical_cast; int main() { string str = "0.6"; double dub = lexical_cast<double>(str); cout << dub << endl; }
Вы можете использовать std::stringstream:
#include <sstream> #include <string> template<typename T> T StringToNumber(const std::string& numberAsString) { T valor; std::stringstream stream(numberAsString); stream >> valor; if (stream.fail()) { std::runtime_error e(numberAsString); throw e; } return valor; }
использование:
double number= StringToNumber<double>("0.6");
да, с лексическим приведением. Используйте stringstream и оператор
ваша собственная версия может выглядеть так:
template<typename to, typename from>to lexical_cast(from const &x) { std::stringstream os; to ret; os << x; os >> ret; return ret; }
вы можете использовать boost лексический бросок:
#include <boost/lexical_cast.hpp> string v("0.6"); double dd = boost::lexical_cast<double>(v); cout << dd << endl;
Примечание: boost:: lexical_cast бросает исключение, поэтому вы должны быть готовы иметь дело с ним, когда вы передаете недопустимое значение, попробуйте передать строку ("xxx")
если вы не хотите, чтобы перетащить в все boost, идти с
strtod(3)
С<cstdlib>
- это уже возвращает значение типа double.#include <iostream> #include <string> #include <cstring> #include <cstdlib> using namespace std; int main() { std::string num = "0.6"; double temp = ::strtod(num.c_str(), 0); cout << num << " " << temp << endl; return 0; }
выходы:
$ g++ -o s s.cc $ ./s 0.6 0.6 $
Почему atof () не работает ... на какой платформе / компиляторе вы находитесь?
У меня была такая же проблема в Linux
double s2f(string str) { istringstream buffer(str); double temp; buffer >> temp; return temp; }
это работает.
этот ответ создает резервную копию litb в ваших комментариях. У меня есть глубокие подозрения, что вы просто не показываете результат должным образом.
однажды со мной случилось то же самое. Я потратил целый день, пытаясь понять, почему я получаю плохое значение в 64-битном int, только чтобы обнаружить, что printf игнорирует второй байт. Вы не можете просто передать 64-разрядное значение в printf, как его int.
способ C++ 11 заключается в использовании std::stod и std::to_string. Оба работают в Visual Studio 11.
, почему
atof()
не работает в исходном вопросе: тот факт, что он брошен в double, вызывает у меня подозрения. Код не должен компилироваться без#include <stdlib.h>
, но если приведение было добавлено для решения предупреждения компиляции, тоatof()
неправильно объявлено. Если компилятор предполагаетatof()
возвращает int, приведение его решит предупреждение о преобразовании, но это будет не причина возвращаемое значение, чтобы быть признанным в качестве двойника.#include <stdlib.h> #include <string> ... std::string num = "0.6"; double temp = atof(num.c_str());
должно работать без предупреждение.
вместо того, чтобы перетаскивать Boost в уравнение, вы можете сохранить свою строку (временно) как
char[]
и использоватьsprintf()
.но, конечно, если вы используете Boost в любом случае, это действительно не слишком большая проблема.
вы не хотите увеличить lexical_cast для string с плавающей точкой в любом случае. Это подмножество вариантов использования является единственным набором, для которого boost последовательно хуже, чем старые функции - и они в основном сосредоточили все свои неудачи там, потому что их собственные результаты производительности показывают 20-25X более низкую производительность, чем использование sscanf и printf для таких преобразований.
Google это самостоятельно. boost:: lexical_cast может обрабатывать что-то вроде 50 преобразований, и если вы исключаете те с плавающей точкой #s его так же хорошо или лучше, как очевидные альтернативы (с дополнительным преимуществом наличия одного API для всех этих операций). Но принесите поплавки и его, как Титаник, ударяющий айсберг с точки зрения производительности.
старые, выделенные str - > двойные функции могут все делать 10000 разборов в чем-то вроде 30 мс (или лучше). lexical_cast занимает что-то вроде 650 мс, чтобы сделать ту же работу.
Моя Проблема:
- независимая от локали строка для double (десятичный разделитель всегда '.')
- обнаружение ошибок при сбое преобразования строк
мое решение (использует функцию Windows _wcstod_l):
// string to convert. Note: decimal seperator is ',' here std::wstring str = L"1,101"; // Use this for error detection wchar_t* stopString; // Create a locale for "C". Thus a '.' is expected as decimal separator double dbl = _wcstod_l(str.c_str(), &stopString, _create_locale(LC_ALL, "C")); if (wcslen(stopString) != 0) { // ... error handling ... we'll run into this because of the separator }
HTH ... мне потребовалось довольно много времени, чтобы добраться до этого решения. И у меня все еще есть ощущение, что я недостаточно знаю о локализации строк и прочее...