std:: строка с плавающей или двойной


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

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

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

15 76
c++

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.

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

способ 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 мс, чтобы сделать ту же работу.

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

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

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