Nasıl bir çift C ++ dize dönüştürür?


171

Bir dize olarak bir çift depolamak gerekir. Bunu printfgörüntülemek istedim eğer kullanabilirsiniz biliyorum , ama ben daha sonra bir harita ( değer olarak , anahtar olarak ) saklayabilirsiniz böylece bir dize değişkeni saklamak istiyorum .


2
Sorunuzu cevaplamak için bir soru: Çifte değeri neden bir haritada saklamak için bir dizede saklıyorsunuz? Anahtar olarak string-ified double'ı kullanacak mısınız? Değilse, neden çifte olduğu gibi bırakmıyorsunuz?
Matt McClellan

1
İlginç bir nokta. Bununla birlikte, çiftin bir harita anahtarı olarak kullanılması tehlikeyle dolu olabilir, ancak kayan nokta değerleri üzerinde tam karşılaştırmalar her zaman olduğu gibi. Bir dize temsilinde endeksleme sorunu önler.
Fred Larson

2
Neden hiç dönüştürmüyorsun? Haritada bir çift olarak saklayın ve dönüş ve dönüşten kaçının.
EvilTeach

3
Hala nesneler için bir çağrı gibi geliyor. Bir birlik işe yarar. Her nesne içine çeşitli değerler eklemek ve kendi kendini doğrulamasını sağlamak.
EvilTeach

2
Bir dosyada sadece bir grup isim / değer çifti var. Nesne gerektirmez.
Kertenkele Bill

Yanıtlar:


183

Boost (tm) yol:

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

Standart C ++ yol:

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

Not : Unutma#include <sstream>


3
Bence boost :: lexical_cast standart C ++ yolu IS, sadece sizin için güzel paketlenmiş. BTW, litb, orada küçük bir yazım hatası var - "boot: lexical_cast".
Fred Larson

2
boost :: lexical_cast sadece stringstream kodu etrafında basit bir paket değildir. Dönüştürme rutinlerinin çoğu yerinde uygulanır. Bu sayfanın altındaki performans ölçümlerine göre ( boost.org/doc/libs/1_47_0/libs/conversion/lexical_cast.htm ) boost :: lexical_cast, stringstreams kullanmaktan daha hızlı ve çoğu durumda scanf / printf
Ferruccio

1
@ Basit bir sarıcı olduğunu kim söyledi? Ve teşekkürler bağlantısını sağlamak için, aslında did o olduğunu düşünüyorum az ya da çok basit bir sarmalayıcı :)
Johannes Schaub - LITB

27
#include <sstream>c ++ yolu için unutma :)
VladL

3
Belgeleme amacıyla, yapmazsanız #include <sstream>, "eksik türe izin verilmiyor" hatası alırsınız.
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
C ++ yolunuz çalışmaz çünkü operator <<a std::ostream&yerine döndürür stringstream&.
Konrad Rudolph

Dize akışlarım biraz paslı görünüyor, ben 'C yollarını tercih ediyorum. Şimdi düzeltildi (umarım).
Adam Rosenfield

C kodunuz ilk başta beni attı. Sizi hala doğru alternatifler verdiğiniz için onayladım.
Kertenkele Bill

2
C yolu dahil etmek için oy verin. benim için çok daha temiz görünüyor.
Nealon

11
C ++ 11 yolu için seçildi. C ++ için yeniyim ve bir to_stringişlev olduğunu fark etmedim . Microsoft Visual C ++ 2013 kullanıyorum.
Trevor Sullivan

123

Standart C ++ 11 yolu (eğer çıkış biçimi umurumda değil ise):

#include <string>

auto str = std::to_string(42.5); 

to_stringN1803 (r0), N1982 (r1) ve N2408 (r2) " Basit Sayısal Erişim " de tanıtılan yeni bir kütüphane işlevidir . stodTers işlemi gerçekleştirme işlevi de vardır .

Farklı bir çıktı biçimine sahip olmak istiyorsanız , diğer yanıtlarda gösterildiği gibi veya yöntemlerini "%f"kullanın .snprintfostringstream


3
Oh evet bebek. to_string ve her ikisi de Visual Studio 11'de çalışıyor.
BSalita

Ah sevgili bebeğim ... to_string, VisualStudio 2010'da çalışmıyor gibi görünüyor): Bu ya da ne yaptığımı bilmiyorum (çok mümkün)
chessofnerd

1
Bu daha modern olmalı, çünkü daha modern!
gsamaras

1
Bu işlevi gerekenden daha fazla ondalık sayı eklememenin bir yolu var mı? Çift dönüştürdüğümde 8.0bana ip verir "8.000000", "8"mükemmel olur.
HelloGoodbye

1
Bu, küçük sayılar için çalışmaz ... örneğin: 1e-9üretir0.000000
user3728501

24

C ++ kullanıyorsanız kaçının sprintf. Un-C ++ y ve çeşitli sorunları var. Dize akışları, tercihen Boost.LexicalCast'te olduğu gibi oldukça kolayca yapılabilen seçim yöntemidir :

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

Kullanımı:

string s = to_string(42.5);

24

C ++ 11'de std :: to_string kullanabilirsiniz

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

Rakamlarım çok küçüktü ve std::to_string()sadece bilimsel formda değil 0.000000 değerini döndürdü.
erfan

11

sprintftamam, ancak C ++ 'da, dönüşüm yapmanın daha iyi, daha güvenli ve biraz daha yavaş yolu şudur stringstream:

#include <sstream>
#include <string>

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

Ayrıca Boost.LexicalCast kullanabilirsiniz :

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

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

Her iki durumda da, daha sonra strolmalıdır "453.23". LexicalCast, dönüşümün tamamlanmasını sağlaması açısından bazı avantajlara sahiptir. stringstreamDahili olarak s kullanır .


10

Ben bakardım C ++ dize Toolkit Libary . Sadece başka bir yerde benzer bir cevap gönderdi. Çok hızlı ve güvenilir buldum.

#include <strtk.hpp>

double pi = M_PI;
std::string pi_as_string  = strtk::type_to_string<double>( pi );


6

Lexical_cast ile ilgili sorun, hassasiyetin tanımlanamamasıdır. Normalde, bir çifti bir dizeye dönüştürüyorsanız, bunun nedeni onu yazdırmak istemenizdir. Hassasiyet çok fazla veya çok azsa, çıktınızı etkiler.



4

Heh, ben sadece yazdım (bu soru ile ilgisiz):

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

/* rest of the code */


2

sprintf()Ve aileye bir göz atın .


2
Printf'den bahsettim, çünkü googling, double'ı printf kullandığınız bir dizeye dönüştürmek için söylenen bir grup makaleyi ortaya çıkardı. Yapabileceğin tek şeyin baskı olduğunu varsayıyorum, benim durumumda yanlış.
Kertenkele Bill

neden -1 oy verdiniz? Bence sprintf iyi. @ BillillLizard, sprint bir şey bir char * değil ekranına yazdırır. Birisi c yönteminin hala çok oy aldığını yanıtladı.
worldterminator

2

Normalde bu işlemler için ecvt, fcvt veya gcvt İşlevlerini kullanmanız gerekir:

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

İşlev olarak:

void double_to_char(double f,char * buffer){
  gcvt(f,10,buffer);
}

0

Daha kompakt bir stil deneyebilirsiniz:

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

Kullanın to_string().
misal :

#include <iostream>   
#include <string>  

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

  return 0;
}

kendiniz çalıştırın: http://ideone.com/7ejfaU
Bunlar da mevcuttur:

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

Bu işlevi kullanarak herhangi bir şeyi herhangi bir şeye dönüştürebilirsiniz:

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

kullanım:

std::string str = to(2.5);
double d = to<double>("2.5");
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.