Подтвердить что ты не робот

Std::string для плавания или двойного

Я пытаюсь преобразовать std::string в float/double. Я пробовал:

std::string num = "0.6";
double temp = (double)atof(num.c_str());

Но он всегда возвращает ноль. Любые другие способы?

4b9b3361

Ответ 1

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 будет быстрее.

Ответ 2

Стандартная библиотека (С++ 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>

Ответ 3

Лексический литой очень приятно.

#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;
}

Ответ 4

Вы можете использовать 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");

Ответ 5

Да, с лексической литой. Используйте поток строк и < оператора или использовать Boost, они уже реализовали его.

Ваша собственная версия может выглядеть так:

template<typename to, typename from>to lexical_cast(from const &x) {
  std::stringstream os;
  to ret;

  os << x;
  os >> ret;

  return ret;  
}

Ответ 6

Вы можете использовать лексический бросок boost:

#include <boost/lexical_cast.hpp>

string v("0.6");
double dd = boost::lexical_cast<double>(v);
cout << dd << endl;

Примечание: boost:: lexical_cast генерирует исключение, поэтому вы должны быть готовы справиться с ним при передаче недопустимого значения, попробуйте передать строку ( "xxx" )

Ответ 7

Если вы не хотите перетаскивать весь импульс, перейдите с 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() не работает... на какой платформе/компиляторе вы работаете?

Ответ 8

У меня была такая же проблема в Linux

double s2f(string str)
{
 istringstream buffer(str);
 double temp;
 buffer >> temp;
 return temp;
}

он работает.

Ответ 9

Этот ответ поддерживает подсветку ваших комментариев. У меня есть глубокие подозрения, что вы просто не показываете результат должным образом.

У меня одно и то же случилось со мной однажды. Я потратил целый день, пытаясь понять, почему я получаю плохое значение в 64-битном int, но обнаружил, что printf игнорирует второй байт. Вы не можете просто передать 64-битное значение в printf, как его int.

Ответ 10

   double myAtof ( string &num){
      double tmp;
      sscanf ( num.c_str(), "%lf" , &tmp);
      return tmp;
   }

Ответ 11

Путь С++ 11 - использовать std:: stod и std:: to_string. Оба работают в Visual Studio 11.

Ответ 12

Что касается того, почему atof() не работает в исходном вопросе: тот факт, что он бросает двойное, делает меня подозрительным. Код не должен компилироваться без #include <stdlib.h>, но если добавление было добавлено для решения предупреждения компиляции, то atof() неправильно объявлен. Если компилятор предполагает, что atof() возвращает int, то его выполнение решит предупреждение о преобразовании, но это не приведет к признанию возвращаемого значения как double.

#include <stdlib.h>
#include <string>

... 
  std::string num = "0.6";
  double temp = atof(num.c_str());

должен работать без предупреждений.

Ответ 13

Вместо того, чтобы перетаскивать Boost в уравнение, вы можете сохранить свою строку (временно) как char[] и использовать sprintf().

Но, конечно, если вы используете Boost в любом случае, это действительно не слишком большая проблема.

Ответ 14

В любом случае вы не хотите Boost lexical_cast для строки ↔ с плавающей запятой. Это подмножество вариантов использования - это единственный набор, для которого усиление последовательно хуже, чем более старые функции, и они в основном сконцентрировали все свои неудачи там, потому что их собственные результаты производительности показывают производительность на уровне 20-25X SLOWER, чем использование sscanf и printf для таких преобразований.

Google это сам. boost:: lexical_cast может обрабатывать что-то вроде 50 преобразований, и если вы исключаете те из них, которые содержат с плавающей точкой #s, как хорошие или лучшие, как очевидные альтернативы (с дополнительным преимуществом наличия единого API для всех этих операций). Но принесите поплавки и его, как "Титаник", ударяющий по айсбергу с точки зрения производительности.

Старые выделенные str- > double функции могут делать 10000 парсетов примерно в 30 мс (или лучше). lexical_cast занимает примерно 650 мс для выполнения той же работы.

Ответ 15

Моя проблема:

  • Локальная независимая строка для двойного (десятичный разделитель всегда '.')
  • Обнаружение ошибок при неудачном преобразовании строк

Мое решение (использует функцию 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... взял меня довольно долго, чтобы добраться до этого решения. И у меня все еще есть ощущение, что я не знаю достаточно о строковой локализации и прочем...