Como converter um duplo em uma string em C ++?

171

Eu preciso armazenar um duplo como uma string. Sei que posso usá-lo printfse quiser exibi-lo, mas só quero armazená-lo em uma variável de cadeia para que possa armazená-lo em um mapa mais tarde (como o valor , não a chave ).

Bill the Lizard
fonte
2
Uma pergunta para responder à sua pergunta: por que você está armazenando o valor duplo em uma string para armazená-lo em um mapa? Você vai usar a string ified double como chave? Se não, por que não deixar o dobro como está?
Matt McClellan
1
Ponto interessante. Usar um duplo como chave de mapa pode estar repleto de perigos, no entanto, como sempre são as comparações exatas nos valores de ponto flutuante. A indexação em uma representação de string evita o problema.
Fred Larson
2
Por que convertê-lo? Armazene-o no mapa como um dobro e evite a conversão de e para.
007 EvilTeach
3
Isso ainda soa como uma chamada para objetos. Um sindicato funcionaria. Cada um dos objetos deve inserir vários valores nele e validá-lo automaticamente.
EvilTeach 2/08/08
2
Eu só tenho um monte de pares nome / valor em um arquivo. Não exige objetos.
Bill the Lizard

Respostas:

183

A maneira boost (tm) :

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

A maneira C ++ padrão :

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

Nota : Não esqueça#include <sstream>

Johannes Schaub - litb
fonte
3
Eu acho que o boost :: lexical_cast é a maneira C ++ padrão, bem embalada para você. BTW, litb, você tem um erro de digitação menor lá - "boot: lexical_cast".
Fred Larson
2
O boost :: lexical_cast não é apenas um invólucro simples em torno do código stringstream. Muitas das rotinas de conversão são implementadas em linha. De acordo com as medições de desempenho na parte inferior desta página ( boost.org/doc/libs/1_47_0/libs/conversion/lexical_cast.htm ), o boost :: lexical_cast é mais rápido que o uso de strings e, na maioria dos casos, mais rápido que o scanf / printf
Ferruccio
1
@Ferr quem disse que era um invólucro simples? E obrigado por fornecer o link, eu realmente fez pensar que era mais ou menos um invólucro simples :)
Johannes Schaub - litb
27
não se esqueça de #include <sstream>para o caminho c ++ :)
VladL
3
Para fins de documentação, caso contrário #include <sstream>, você receberá um erro "tipo incompleto não é permitido".
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
fonte
1
Seu modo de C ++ não funcionará porque operator <<retorna um std::ostream&ao invés de um stringstream&.
Konrad Rudolph
Parece que meus strings estão um pouco enferrujados, prefiro os velhos modos C. Corrigido agora (espero).
Adam Rosenfield
Seu código C me assustou primeiro. Eu ainda te votei por dar alternativas corretas.
Bill the Lizard
2
voto positivo por incluir o caminho C. apenas parece muito mais limpo para mim.
Nealon
11
Promovido para a maneira C ++ 11. Eu sou novo em C ++ e não percebi que havia uma to_stringfunção. Estou usando o Microsoft Visual C ++ 2013.
Trevor Sullivan
123

A maneira C ++ 11 padrão (se você não se importa com o formato de saída):

#include <string>

auto str = std::to_string(42.5); 

to_stringé uma nova função de biblioteca introduzida no " Acesso Numérico Simples " N1803 (r0), N1982 (r1) e N2408 (r2) . Também há a função de executar a operação reversa.stod

Se você deseja ter um formato de saída diferente "%f", use os métodos snprintfou ostringstreamconforme ilustrado em outras respostas.

kennytm
fonte
3
oh sim querida. to_string e stod ambos trabalham no Visual Studio 11.
BSalita
Oh caro bebê ... to_string não aparecer para trabalhar em VisualStudio 2010): Que, ou não sei o que estou fazendo (muito possível)
chessofnerd
1
Isso deve ser maior, pois é mais moderno!
precisa saber é o seguinte
1
Existe alguma maneira de fazer essa função não adicionar mais casas decimais do que o necessário? Quando eu converter o dobro, 8.0isso me dará a corda "8.000000", enquanto "8"seria perfeitamente correto.
HelloGoodbye
1
Isso não funciona para números pequenos ... por exemplo: 1e-9produz0.000000
user3728501 8/16/16
24

Se você usa C ++, evite sprintf. É un-C ++ y e tem vários problemas. Os fluxos de string são o método de escolha, de preferência encapsulado como no Boost.LexicalCast, que pode ser feito com bastante facilidade:

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

Uso:

string s = to_string(42.5);
Konrad Rudolph
fonte
24

Você pode usar std :: to_string no C ++ 11

double d = 3.0;
std::string str = std::to_string(d);
Yochai Timmer
fonte
Meus números eram realmente pequenos e std::to_string()simplesmente retornavam 0,000000 e não na forma científica.
erfan 07/07
11

sprintfestá bem, mas em C ++, a maneira melhor, mais segura e também um pouco mais lenta de fazer a conversão é com stringstream:

#include <sstream>
#include <string>

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

Você também pode usar o Boost.LexicalCast :

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

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

Nos dois casos, strdeve ser "453.23"posterior. O LexicalCast tem algumas vantagens, pois garante que a transformação está completa. Ele usa stringstreams internamente.

coppro
fonte
10

Gostaria de olhar para o C ++ String Toolkit Libary . Apenas postou uma resposta semelhante em outro lugar. Eu achei muito rápido e confiável.

#include <strtk.hpp>

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

Herb Sutter tem um excelente artigo sobre formatação de strings . Eu recomendo a leitura. Eu já o vinculei antes no SO.

Fred Larson
fonte
1
Esta não é uma resposta, mas faria um comentário muito útil sobre a pergunta.
Expiação limitada
6

O problema com lexical_cast é a incapacidade de definir precisão. Normalmente, se você estiver convertendo um duplo em uma sequência, é porque deseja imprimi-la. Se a precisão for muito ou pouco, isso afetaria sua saída.


fonte
4

Você também pode usar stringstream .

Firas Assaad
fonte
4

Heh, acabei de escrever isso (não relacionado a esta pergunta):

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

/* rest of the code */
Vinko Vrsalovic
fonte
2

Você pode ler minha postagem anterior no SO. (Versão em macro com um objeto ostringstream temporário.)

Para constar: No meu próprio código, sou a favor de snprintf (). Com uma matriz de caracteres na pilha local, não é tão ineficiente. (Bem, talvez se você excedeu o tamanho da matriz e fez um loop para fazer isso duas vezes ...)

(Também o envolvi via vsnprintf (). Mas isso me custa uma verificação de tipo. Yelp se você quiser o código ...)

Mr.Ree
fonte
2

Dê uma olhada sprintf()e família.

Darron
fonte
2
Eu mencionei printf porque o Google pesquisou vários artigos que dizem para converter de uma dupla para uma string que você usa printf. Eles assumem que a única coisa que você poderia fazer é imprimir, o que, no meu caso, é falso.
Bill o Lagarto
por que você vota -1? Eu acho que o sprintf é bom. @ BilltheLizard, o sprint imprime algo em uma tela * de caracteres. Alguém respondeu que o método c ainda obteve muitos votos.
worldterminator
2

Normalmente, para essas operações, é necessário usar as funções ecvt, fcvt ou 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   

Como uma função:

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

Você pode tentar um estilo mais compacto:

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
fonte
0

Use to_string().
exemplo:

#include <iostream>   
#include <string>  

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

  return 0;
}

execute você mesmo: http://ideone.com/7ejfaU
Estes também estão disponíveis:

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
fonte
0

Você pode converter qualquer coisa para qualquer coisa usando esta função:

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

uso:

std::string str = to(2.5);
double d = to<double>("2.5");
Sam Mokari
fonte