Я пытаюсь преобразовать std::string
в float/double
.
Я пробовал:
std::string num = "0.6";
double temp = (double)atof(num.c_str());
Но он всегда возвращает ноль. Любые другие способы?
Я пытаюсь преобразовать std::string
в float/double
.
Я пробовал:
std::string num = "0.6";
double temp = (double)atof(num.c_str());
Но он всегда возвращает ноль. Любые другие способы?
std::string num = "0.6";
double temp = ::atof(num.c_str());
Это для меня, это действительный синтаксис С++ для преобразования строки в double.
Вы можете сделать это с помощью stringstream или boost:: lexical_cast, но они имеют ограничение производительности.
Ахаха у вас есть проект Qt...
QString winOpacity("0.6");
double temp = winOpacity.toDouble();
Дополнительная заметка:
Если входные данные являются const char*
, QByteArray::toDouble
будет быстрее.
Стандартная библиотека (С++ 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");
Да, с лексической литой. Используйте поток строк и < оператора или использовать Boost, они уже реализовали его.
Ваша собственная версия может выглядеть так:
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" )
Если вы не хотите перетаскивать весь импульс, перейдите с strtod(3)
из <cstdlib>
- он уже возвращает двойной.
#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;
}
он работает.
Этот ответ поддерживает подсветку ваших комментариев. У меня есть глубокие подозрения, что вы просто не показываете результат должным образом.
У меня одно и то же случилось со мной однажды. Я потратил целый день, пытаясь понять, почему я получаю плохое значение в 64-битном int, но обнаружил, что printf игнорирует второй байт. Вы не можете просто передать 64-битное значение в printf, как его int.
double myAtof ( string &num){
double tmp;
sscanf ( num.c_str(), "%lf" , &tmp);
return tmp;
}
Путь С++ 11 - использовать std:: stod и std:: to_string. Оба работают в Visual Studio 11.
Что касается того, почему atof()
не работает в исходном вопросе: тот факт, что он бросает двойное, делает меня подозрительным. Код не должен компилироваться без #include <stdlib.h>
, но если добавление было добавлено для решения предупреждения компиляции, то atof()
неправильно объявлен. Если компилятор предполагает, что atof()
возвращает int, то его выполнение решит предупреждение о преобразовании, но это не приведет к признанию возвращаемого значения как double.
#include <stdlib.h>
#include <string>
...
std::string num = "0.6";
double temp = atof(num.c_str());
должен работать без предупреждений.
Вместо того, чтобы перетаскивать Boost в уравнение, вы можете сохранить свою строку (временно) как char[]
и использовать sprintf()
.
Но, конечно, если вы используете Boost в любом случае, это действительно не слишком большая проблема.
В любом случае вы не хотите Boost lexical_cast для строки ↔ с плавающей запятой. Это подмножество вариантов использования - это единственный набор, для которого усиление последовательно хуже, чем более старые функции, и они в основном сконцентрировали все свои неудачи там, потому что их собственные результаты производительности показывают производительность на уровне 20-25X SLOWER, чем использование sscanf и printf для таких преобразований.
Google это сам. boost:: lexical_cast может обрабатывать что-то вроде 50 преобразований, и если вы исключаете те из них, которые содержат с плавающей точкой #s, как хорошие или лучшие, как очевидные альтернативы (с дополнительным преимуществом наличия единого API для всех этих операций). Но принесите поплавки и его, как "Титаник", ударяющий по айсбергу с точки зрения производительности.
Старые выделенные str- > double функции могут делать 10000 парсетов примерно в 30 мс (или лучше). lexical_cast занимает примерно 650 мс для выполнения той же работы.
Моя проблема:
Мое решение (использует функцию 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... взял меня довольно долго, чтобы добраться до этого решения. И у меня все еще есть ощущение, что я не знаю достаточно о строковой локализации и прочем...