Jak przekonwertować double na ciąg w C ++?

171

Muszę przechowywać podwójną jako ciąg. Wiem, że mogę go użyć, printfjeśli chcę go wyświetlić, ale chcę go po prostu zapisać w zmiennej ciągu, aby móc później zapisać go na mapie (jako wartość , a nie klucz ).

Bill the Lizard
źródło
2
Pytanie odpowiadające na twoje pytanie: dlaczego przechowujesz podwójną wartość w ciągu, aby zapisać ją na mapie? Czy jako klucza użyjesz podwójnej liczby łańcuchowej? Jeśli nie, dlaczego nie zostawić podwójnej postaci?
Matt McClellan
1
Ciekawy punkt. Używanie podwójnego klucza jako klucza mapy może jednak wiązać się z niebezpieczeństwem, ponieważ dokładne porównania wartości zmiennoprzecinkowych zawsze są. Indeksowanie reprezentacji ciągu pozwala uniknąć problemu.
Fred Larson
2
Po co to w ogóle konwertować? Zapisz go na mapie jako podwójny i unikaj konwersji na iz.
EvilTeach
3
To wciąż brzmi jak wezwanie do przedmiotów. Związek działałby. Każdy obiekt, aby wstawić do niego różne wartości i samemu zweryfikować.
EvilTeach
2
Mam tylko kilka par nazwa / wartość w pliku. Nie wymaga przedmiotów.
Bill the Lizard

Odpowiedzi:

183

Sposób wzmocnienia (tm) :

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

Przez standard C ++ sposób:

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

Uwaga : nie zapomnij#include <sstream>

Johannes Schaub - litb
źródło
3
Myślę, że boost :: lexical_cast JEST prawie standardową metodą C ++, po prostu ładnie zapakowaną dla Ciebie. BTW, litb, masz tam drobną literówkę - "boot: lexical_cast".
Fred Larson
2
boost :: lexical_cast to nie tylko proste opakowanie wokół kodu stringstream. Wiele procedur konwersji jest zaimplementowanych w linii. Zgodnie z pomiarami wydajności na dole tej strony ( boost.org/doc/libs/1_47_0/libs/conversion/lexical_cast.htm ), boost :: lexical_cast jest szybszy niż używanie stringstreams i, w większości przypadków, szybszy niż scanf / printf
Ferruccio
1
@Ferr, kto powiedział, że to proste opakowanie? I dzięki za udostępnienie łącza, tak naprawdę nie sądzę, że było mniej lub bardziej prosty wrapper :)
Johannes Schaub - litb
27
nie zapomnij #include <sstream>o sposobie c ++ :)
VladL
3
Ze względu na dokumentację, jeśli tego nie zrobisz #include <sstream>, pojawi się błąd „niepełny typ jest niedozwolony”.
Trevor Sullivan
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);
Adam Rosenfield
źródło
1
Twój sposób C ++ nie zadziała, ponieważ operator <<zwraca std::ostream&zamiast a stringstream&.
Konrad Rudolph
Wygląda na to, że moje struny są trochę zardzewiałe, wolę stare sposoby. Naprawiono teraz (mam nadzieję).
Adam Rosenfield
Twój kod C z początku mnie wyrzucił. Nadal głosowałem za podaniem właściwych alternatyw.
Bill the Lizard
2
Głosuj za włączeniem metody C. po prostu wydaje mi się o wiele czystszy.
Nealon
11
Uznany za sposób C ++ 11. Jestem nowy w C ++ i nie zdawałem sobie sprawy, że istnieje to_stringfunkcja. Używam Microsoft Visual C ++ 2013.
Trevor Sullivan
123

Standardowa C ++ 11 sposób (jeśli nie dbają o format wyjściowy):

#include <string>

auto str = std::to_string(42.5); 

to_stringto nowa funkcja biblioteczna wprowadzona w N1803 (r0), N1982 (r1) i N2408 (r2) „ Prosty dostęp numeryczny ”. Istnieje również stodfunkcja wykonywania operacji odwrotnej.

Jeśli chcesz mieć inny format wyjściowy niż "%f", użyj metod snprintflub ostringstream, jak pokazano w innych odpowiedziach.

kennytm
źródło
3
Oh tak kochanie. to_string i stod oba działają w Visual Studio 11.
BSalita
Ojej kochanie ... to_string nie działa w VisualStudio 2010): To albo nie wiem, co robię (bardzo możliwe)
chessofnerd
1
To powinno być wyższe, ponieważ jest bardziej nowoczesne!
gsamaras
1
Czy istnieje sposób, aby ta funkcja nie dodawała większej liczby miejsc po przecinku, niż potrzeba? Kiedy konwertuję dublet 8.0, otrzymam strunę "8.000000", podczas gdy "8"byłoby idealnie.
HelloGoodbye,
1
To nie działa dla małych liczb ... np: 1e-9produkuje0.000000
user3728501
24

Jeśli używasz C ++, unikaj sprintf. Nie jest napisane w C ++ i ma kilka problemów. Stringstreams to metoda z wyboru, najlepiej hermetyzowana, jak w Boost.LexicalCast, co można zrobić dość łatwo:

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

Stosowanie:

string s = to_string(42.5);
Konrad Rudolph
źródło
24

Możesz użyć std :: to_string w C ++ 11

double d = 3.0;
std::string str = std::to_string(d);
Yochai Timmer
źródło
Moje liczby były naprawdę małe i std::to_string()po prostu zwróciły 0,000000, a nie w formie naukowej.
erfan
11

sprintfjest w porządku, ale w C ++ lepszym, bezpieczniejszym i nieco wolniejszym sposobem konwersji jest stringstream:

#include <sstream>
#include <string>

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

Możesz także użyć Boost.LexicalCast :

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

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

W obu przypadkach strpowinno być "453.23"później. LexicalCast ma pewne zalety, ponieważ zapewnia całkowitą transformację. Używa stringstreams wewnętrznie.

coppro
źródło
10

Spojrzałbym na C ++ String Toolkit Libary . Właśnie opublikowałem podobną odpowiedź w innym miejscu. Okazało się, że jest bardzo szybki i niezawodny.

#include <strtk.hpp>

double pi = M_PI;
std::string pi_as_string  = strtk::type_to_string<double>( pi );
DannyK
źródło
6

Problem z lexical_cast polega na niemożności zdefiniowania precyzji. Zwykle, jeśli konwertujesz double na ciąg, dzieje się tak, ponieważ chcesz go wydrukować. Jeśli precyzja jest za duża lub za mała, wpłynie to na wynik.


źródło
4

Możesz także użyć stringstream .

Firas Assaad
źródło
4

Heh, właśnie napisałem to (niezwiązane z tym pytaniem):

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

/* rest of the code */
Vinko Vrsalovic
źródło
2

Możesz przeczytać mój wcześniejszy post na SO. (Wersja makro z tymczasowym obiektem ostringstream.)

Dla przypomnienia: w moim własnym kodzie preferuję snprintf (). Z tablicą char na lokalnym stosie nie jest to takie nieefektywne. (Cóż, może jeśli przekroczyłeś rozmiar tablicy i zapętlono, aby zrobić to dwukrotnie ...)

(Zapakowałem to również za pomocą vsnprintf (). Ale to kosztuje mnie trochę sprawdzenia typu. Yelp, jeśli chcesz kod ...)

Panie Ree
źródło
2

Przyjrzyj się sprintf()i rodzinie.

Darron
źródło
2
Wspomniałem o printf, ponieważ wyszukiwanie w Google przyniosło kilka artykułów, które mówią, że należy zamienić podwójną na ciąg, którego używasz printf. Zakładają, że jedyne, co możesz zrobić, to drukowanie, co w moim przypadku jest fałszywe.
Bill the Lizard
dlaczego głosujesz -1? Myślę, że sprintf jest dobry. @BilltheLizard, sprint drukuje coś do znaku * nie ekranu. Ktoś odpowiedział c metoda nadal ma dużo głosów.
worldterminator
2

Normalnie dla tych operacji musisz użyć funkcji ecvt, fcvt lub 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   

Jako funkcja:

void double_to_char(double f,char * buffer){
  gcvt(f,10,buffer);
}
Ingo
źródło
0

Możesz wypróbować bardziej kompaktowy styl:

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(); 
Alexis Sánchez Tello
źródło
0

Użyj to_string().
przykład:

#include <iostream>   
#include <string>  

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

  return 0;
}

uruchom go samodzielnie: http://ideone.com/7ejfaU
Te są również dostępne:

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
źródło
0

Możesz przekonwertować dowolną rzecz na cokolwiek za pomocą tej funkcji:

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

stosowanie :

std::string str = to(2.5);
double d = to<double>("2.5");
Sam Mokari
źródło