Как я могу преобразовать двойной в строку в C ++?

171

Мне нужно хранить двойной как строка. Я знаю, что могу использовать, printfесли хочу отобразить его, но я просто хочу сохранить его в строковой переменной, чтобы потом сохранить его на карте (как значение , а не ключ ).

Билл Ящерица
источник
2
Вопрос для ответа на ваш вопрос: почему вы храните двойное значение в строке, чтобы сохранить его на карте? Собираетесь ли вы использовать строковое двойное в качестве ключа? Если нет, то почему бы не оставить двойной как есть?
Мэтт Макклеллан
1
Интересный момент. Однако использование double в качестве ключа карты может быть сопряжено с опасностью, поскольку точные сравнения значений с плавающей запятой всегда есть. Индексирование по строковому представлению устраняет проблему.
Фред Ларсон
2
Зачем конвертировать это вообще? Храните его на карте как двойное и избегайте конвертации в и из.
EvilTeach
3
Это все еще звучит как призыв к объектам. Союз будет работать. Каждый объект для вставки различных значений в него, и он сам проверяется.
EvilTeach
2
У меня есть только несколько пар имя / значение в файле. Это не требует объектов.
Билл Ящерица

Ответы:

183

Способ повышения (тм) :

std::string str = boost::lexical_cast<std::string>(dbl);

В Standard C ++ способ:

std::ostringstream strs;
strs << dbl;
std::string str = strs.str();

Примечание : не забудьте#include <sstream>

Йоханнес Шауб - Литб
источник
3
Я думаю, что boost :: lexical_cast в значительной степени является стандартным способом C ++, просто прекрасно упакованным для вас. Кстати, у вас есть небольшая опечатка - boot: lexical_cast.
Фред Ларсон
2
boost :: lexical_cast - это не просто оболочка для кода с потоком строк. Многие из процедур преобразования реализованы встроенными. Согласно измерениям производительности в нижней части этой страницы ( boost.org/doc/libs/1_47_0/libs/conversion/lexical_cast.htm ), boost :: lexical_cast быстрее, чем использование stringstream, и, в большинстве случаев, быстрее, чем scanf / printf
Ферруччо
1
@ Ферр, кто сказал, что это простая обертка? И спасибо за предоставленную ссылку, я на самом деле так думаю , что это было более или менее простой оберткой :)
Johannes Schaub - LITB
27
не забудьте #include <sstream>для пути с ++ :)
VladL
3
Ради документации, если вы этого не сделаете #include <sstream>, вы получите ошибку «неполный тип не допускается».
Тревор Салливан
194
// The C way:
char buffer[32];
snprintf(buffer, sizeof(buffer), "%g", myDoubleVar);

// The C++03 way:
std::ostringstream sstream;
sstream << myDoubleVar;
std::string varAsString = sstream.str();

// The C++11 way:
std::string varAsString = std::to_string(myDoubleVar);

// The boost way:
std::string varAsString = boost::lexical_cast<std::string>(myDoubleVar);
Адам Розенфилд
источник
1
Ваш способ C ++ не будет работать, потому что operator <<возвращает std::ostream&скорее, чем stringstream&.
Конрад Рудольф
Кажется, мои струнные потоки немного ржавые, я предпочитаю старые способы. Исправлено сейчас (надеюсь).
Адам Розенфилд
Ваш код на C сначала сбил меня с толку. Я все еще поддерживал тебя за то, что ты дал правильные альтернативы.
Билл Ящерица
2
upvote для включения пути C. просто кажется мне намного чище.
Нилон
11
Голосование за C ++ 11. Я новичок в C ++, и не понял, что там была to_stringфункция. Я использую Microsoft Visual C ++ 2013.
Тревор Салливан
123

Стандарт C ++ 11 способ (если вы не заботитесь о формате вывода):

#include <string>

auto str = std::to_string(42.5); 

to_stringэто новая библиотечная функция, представленная в N1803 (r0), N1982 (r1) и N2408 (r2) « Простой числовой доступ ». Есть также stodфункция для выполнения обратной операции.

Если вы хотите использовать другой формат вывода "%f", используйте методы snprintfили, ostringstreamкак показано в других ответах.

kennytm
источник
3
о да, детка. to_string и stod обе работают в Visual Studio 11.
BSalita
О, дорогой, детка ... to_string не работает в VisualStudio 2010): Это, или я не знаю, что я делаю (очень возможно)
chessofnerd
1
Это должно быть выше, так как это более современно!
gsamaras
1
Есть ли способ заставить эту функцию не добавлять больше десятичных дробей, чем необходимо? Когда я конвертирую двойное, 8.0это дает мне строку"8.000000" , хотя "8"все будет в порядке.
Здравствуйте, до свидания,
1
Это не работает для небольших чисел ... например: 1e-9производит0.000000
пользователь3728501
24

Если вы используете C ++, избегайте sprintf. Это не-C ++ y и имеет несколько проблем. Stringstream - это метод выбора, предпочтительно инкапсулированный, как в Boost.LexicalCast, который можно сделать довольно легко:

template <typename T>
std::string to_string(T const& value) {
    stringstream sstr;
    sstr << value;
    return sstr.str();
}

Использование:

string s = to_string(42.5);
Конрад Рудольф
источник
24

Вы можете использовать std :: to_string в C ++ 11

double d = 3.0;
std::string str = std::to_string(d);
Йохай Тиммер
источник
Мои цифры были очень малы и std::to_string()просто вернули 0,000000, а не в научной форме.
Эрфан
11

sprintfвсе в порядке, но в C ++ лучший, более безопасный и немного медленный способ преобразования stringstream:

#include <sstream>
#include <string>

// In some function:
double d = 453.23;
std::ostringstream os;
os << d;
std::string str = os.str();

Вы также можете использовать Boost.LexicalCast :

#include <boost/lexical_cast.hpp>
#include <string>

// In some function:
double d = 453.23;
std::string str = boost::lexical_cast<string>(d);

В обоих случаях strдолжно быть "453.23"потом. LexicalCast имеет некоторые преимущества в том, что он обеспечивает завершение преобразования. Он использует stringstreams внутри.

coppro
источник
10

Я бы посмотрел на C ++ String Toolkit Libary . Просто опубликовал аналогичный ответ в другом месте. Я нашел это очень быстро и надежно.

#include <strtk.hpp>

double pi = M_PI;
std::string pi_as_string  = strtk::type_to_string<double>( pi );
DannyK
источник
6

Проблема с lexical_cast заключается в невозможности определить точность. Обычно, если вы конвертируете double в строку, это потому, что вы хотите распечатать ее. Если точность слишком велика или слишком мала, это повлияет на ваш результат.


источник
4

Хех, я только что написал это (не имеет отношения к этому вопросу):

string temp = "";
stringstream outStream;
double ratio = (currentImage->width*1.0f)/currentImage->height;
outStream << " R: " << ratio;
temp = outStream.str();

/* rest of the code */
Винко Врсалович
источник
2

Вы можете прочитать мои предыдущие публикации на SO. (Макро-версия с временным объектом ostringstream.)

Для записи: в моем собственном коде я предпочитаю snprintf (). С массивом char в локальном стеке это не так неэффективно. (Ну, может быть, если вы превысили размер массива и зациклились, чтобы сделать это дважды ...)

(Я также обернул это через vsnprintf (). Но это стоит мне некоторой проверки типа. Yelp, если вы хотите код ...)

Mr.Ree
источник
2

Взгляните и на sprintf()семью.

Darron
источник
2
Я упомянул printf, потому что googling нашел кучу статей, в которых говорится, что для преобразования из двойного в строку вы используете printf. Они предполагают, что единственное, что вы можете сделать, - это печатать, что в моем случае неверно.
Билл Ящерица
почему ты голосуешь -1? Я думаю, что спринтф это хорошо. @BilltheLizard, sprint печатает что-то на символе *, а не на экране. Кто-то ответил c метод все еще получил много голосов.
определитель мира
2

Обычно для этих операций вы должны использовать функции ecvt, fcvt или gcvt:

/* gcvt example */
#include <stdio.h>
#include <stdlib.h>

main ()
{
  char buffer [20];
  gcvt (1365.249,6,buffer);
  puts (buffer);
  gcvt (1365.249,3,buffer);
  puts (buffer);
  return 0;
}

Output:
1365.25
1.37e+003   

Как функция:

void double_to_char(double f,char * buffer){
  gcvt(f,10,buffer);
}
Инго
источник
0

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

std::string number_in_string;

double number_in_double;

std::ostringstream output;

number_in_string = (dynamic_cast< std::ostringstream*>(&(output << number_in_double <<

std::endl)))->str(); 
Алексис Санчес Телло
источник
0

Использование to_string().
пример :

#include <iostream>   
#include <string>  

using namespace std;
int main ()
{
    string pi = "pi is " + to_string(3.1415926);
    cout<< "pi = "<< pi << endl;

  return 0;
}

запустите его сами: http://ideone.com/7ejfaU
Они также доступны:

string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned long val);
string to_string (unsigned long long val);
string to_string (float val);
string to_string (double val);
string to_string (long double val);
Rika
источник
0

Вы можете конвертировать любую вещь во что угодно, используя эту функцию:

template<class T = std::string, class U>
T to(U a) {
    std::stringstream ss;
    T ret;
    ss << a;
    ss >> ret;
    return ret;
};

использование :

std::string str = to(2.5);
double d = to<double>("2.5");
Сэм Мокари
источник