Вопрос по c++ – std :: string, чтобы плавать или удваивать

82

Я пытаюсь конвертироватьstd::string вfloat/double. I tried:

<code>std::string num = "0.6";
double temp = (double)atof(num.c_str());
</code>

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

Не поддавайся стремлению завладеть чем-то уже десять лет назад. haavee
Вы уверены, что у вас установлена правильная локаль? попробуйте "0,6" или setlocale (LC_NUMERIC, "C"); Johannes Schaub - litb
Вы уверены, что выводите его правильно? Это не должно давать ноль Johannes Schaub - litb
Кроме того, вам не нужно разыгрывать atof, он уже возвращает double. AlbertoPL
Я уверен. Отладчик показывает мне 0. И результат 0. Платформа: Linux. Max Frai

Ваш Ответ

15   ответов
87

с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>

Этоотличны знать, что комитет по стандартам C ++ добавил это.ostringstream само по себе просто слишком долго печатать, не говоря уже об использовании .. bobobobo
Мне нравится это решение, но похоже, что оно только из C ++ 11. Поэтому недоступно в моем SDK. pamplemousse_mk2
Для чисел с плавающей запятой (как было задано в вопросе, который я нашел в Google, набрав «c ++ string to float»), нужно использовать std :: stof. Étienne
Просто обратите внимание, что это может привести к исключениям: std :: invalid_argument (если преобразование не удалось) std :: out_of_range (если выходит за пределы диапазона) Jason Doucette
Покупатель, будьте осторожны, зависит от текущей локали. nmr
9

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

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

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

  os << x;
  os >> ret;

  return ret;  
}
1

я, что вы просто неправильно отображаете результат.

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

Я не использую printf, чтобы увидеть результаты ... И я использую это значение, чтобы установить прозрачность окна, и мое окно полностью прозрачно, поэтому значение равно 0. Max Frai
1
   double myAtof ( string &num){
      double tmp;
      sscanf ( num.c_str(), "%lf" , &tmp);
      return tmp;
   }
Неправильный ответ. Откуда вы знаете, что значение, хранящееся в num, является действительным числом с плавающей запятой? вы не проверяете возвращаемый тип sscanf, похоже на стиль кодирования MS. Matthieu N.
27

Лексический актерский состав очень хорош.

#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;
}
+ 1 за то, что не использовал "using namespace std;" Johannes Schaub - litb
Хорошая особенность boost :: lexical_cast - обработка ошибок. В случае сбоя преобразования выдается исключение:try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion } Semjon Mössinger
Чтобы быть более точным, используйтеcatch ( boost::bad_lexical_cast const& err ) чтобы поймать исключение. Semjon Mössinger
Спасибо, это работает .. Но это вопрос для меня: почему мой код не работает. Max Frai
@ Йоханнес Шауб: Основываясь на ADL, он мог бы также иметь, использование определений плюс то, что он фактически использует, вероятно, принесет в область применения огромное количество стандартных элементов. Кроме того, lexical_cast безумно медленный, так что +1 от меня нет. Matthieu N.
110
std::string num = "0.6";
double temp = ::atof(num.c_str());

это правильный синтаксис C ++ для преобразования строки в двойное число.

Вы можете сделать это с помощью stringstream или boost :: lexical_cast, но это может привести к снижению производительности.

Ахаха, у тебя есть проект Qt ...

QString winOpacity("0.6");
double temp = winOpacity.toDouble();

Дополнительная заметка:
Если входные данные являютсяconst char*, QByteArray::toDouble будет быстрее.

Я не вижу причин, по которым boost :: lexical_cast может снизить производительность (но поток строк определенно медленнее). Zifre
boost :: lexical_cast в потоковом режиме. TimW
@ ShaChris Потому что я хочу убедиться, что я использую функцию atof из глобального пространства имен. TimW
Думаю, вы не можете сказать, что они приходят с потерей производительности. Подумайте о том, что происходит, когда перед этим у вас есть cin >> num ;. Пользователь должен будет очень быстро печатать (например, rly jon skeet), чтобы заметить, что lexical_cast медленнее, чем миллисекунды :) Тем не менее, я считаю, что есть задачи, в которых lexical_cast просто высасывает слишком большую производительность:) Johannes Schaub - litb
Для этого решения, что делает :: перед atof ()? Что это должно быть там? sivabudh
14

Вы можете использовать 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");
@ JEan-Phillippe Jodiun Я ответил на удаленный комментарий, где кто-то рекомендовал Boost. Я знаю, что Повышение в большинстве случаев является излишним. Кстати, с некоторых пор использование Boost ограничено «более новыми» компиляторами. Старые проекты не могут использовать Boost. Например, ASIO сильно зависит от C ++ 11-функций, таких как std :: addressof, что делает его совершенно бесполезным для компиляторов C ++ 98 / C ++ 03. ИМХО, когда проект начинался, было намерение Boost предоставить новые «стандартизированные» функции для более старых версий компилятора ...: - kirsche40
@ kirsche40 Похоже, это хорошая альтернатива для людей, у которых еще нет зависимостей с помощью Boost (связывать с Boost только для преобразования std :: string в числа немного излишне!) Jean-Philippe Jodoin
Мм, ты думаешь, что у boost :: lexical_cast ужасный интерфейс? Посмотрите на ответ stefanB! Boost делает то же самое. kirsche40
4

Если ты не хочешь тянуть всю надстройку, иди с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;
}

Outputs:

$ g++ -o s s.cc
$ ./s
0.6 0.6
$

Почему atof () не понимает, орк ... на какой платформе / компиляторе вы работаете?

+ 1 за неиспользование буста developerbmw
Использование струнного потока не потребует повышения jalf
Ваш метод тоже возвращает ноль. Linux. Max Frai
3

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

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

оно работает

7

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

#include <boost/lexical_cast.hpp>

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

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

0

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

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

1

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

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

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

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

0

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

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

1

: stod и std :: to_string. Оба работают в Visual Studio 11.

0

-> с плавающей точкой. Это подмножество вариантов использования является единственным набором, для которого усиление постоянно хуже, чем у более старых функций, и они в основном сконцентрировали там все свои неудачи, потому что их собственные результаты показывают производительность в 20-25 раз МЕНЬШЕ, чем использование sscanf и printf для таких преобразований.

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

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

Нет источника? Я гуглил это сам: Boost.org / док / ЛИЭС / 1_55_0 / DOC / HTML / boost_lexical_cast / ... Blake

Похожие вопросы