Я пытаюсь преобразовать 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());
Для меня это правильный синтаксис 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>
ostringstreamсам по себе был слишком длинным, чтобы печатать, не говоря уже об использовании ..
Лексический состав очень приятный.
#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;
}
try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
catch ( boost::bad_lexical_cast const& err )для перехвата исключения.
Вы можете использовать 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;
}
Вы можете использовать усиление лексического приведения:
#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)from <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 () не работает ... на какой платформе / компиляторе вы работаете?
double myAtof ( string &num){
double tmp;
sscanf ( num.c_str(), "%lf" , &tmp);
return tmp;
}
Этот ответ подкреплен вашими комментариями. У меня есть глубокие подозрения, что вы просто неправильно показываете результат.
Однажды со мной случилось то же самое. Я потратил целый день, пытаясь понять, почему я получил плохое значение в 64-битном int, только чтобы обнаружить, что printf игнорирует второй байт. Вы не можете просто передать 64-битное значение в printf, как int.
Что касается того, почему atof()не работает в исходном вопросе: тот факт, что он приведен к удвоению, вызывает у меня подозрения. Код не должен компилироваться без него #include <stdlib.h>, но если приведение было добавлено для устранения предупреждения компиляции, atof()оно объявлено неправильно. Если компилятор предполагает, что atof()возвращает int, его приведение устранит предупреждение о преобразовании, но не приведет к тому, что возвращаемое значение будет распознано как двойное.
#include <stdlib.h>
#include <string>
...
std::string num = "0.6";
double temp = atof(num.c_str());
должен работать без предупреждений.
Вместо того, чтобы перетаскивать Boost в уравнение, вы можете оставить свою строку (временно) как a char[]и использовать sprintf().
Но, конечно, если вы все равно используете Boost, это не такая уж большая проблема.
В любом случае вам не нужно Boost lexical_cast для строки <-> с плавающей запятой. Это подмножество вариантов использования - единственный набор, для которого ускорение постоянно хуже, чем у старых функций, и они в основном сосредоточили все свои отказы именно там, потому что их собственные результаты производительности показывают производительность в 20-25 раз МЕДЛЕННУЮ, чем при использовании sscanf и printf для таких преобразований.
Погуглите сами. 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 ... мне потребовалось довольно много времени, чтобы добраться до этого решения. И у меня до сих пор такое чувство, что я недостаточно разбираюсь в локализации строк и тому подобном ...