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 ).


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>


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);

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.


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);

24

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

double d = 3.0;
std::string str = std::to_string(d);

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.


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 );


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.



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 */


2

Przyjrzyj się sprintf()i rodzinie.


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

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(); 

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);

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");
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.