¿Cómo convierto un doble en una cadena en C ++?

171

Necesito almacenar un doble como una cadena. Sé que puedo usar printfsi quisiera mostrarlo, pero solo quiero almacenarlo en una variable de cadena para poder almacenarlo en un mapa más tarde (como el valor , no la clave ).

Bill el lagarto
fuente
2
Una pregunta para responder a su pregunta: ¿por qué está almacenando el valor doble en una cadena para almacenarlo en un mapa? ¿Vas a usar el doble de cadena como clave? Si no, ¿por qué no dejar el doble como está?
Matt McClellan
1
Punto interesante Sin embargo, usar un doble como clave de mapa puede estar lleno de peligros, ya que las comparaciones exactas de los valores de coma flotante siempre lo son. La indexación en una representación de cadena evita el problema.
Fred Larson
2
¿Por qué convertirlo? Guárdelo en el mapa como un doble y evite la conversión hacia y desde.
EvilTeach
3
Eso todavía suena como una llamada a objetos. Un sindicato funcionaría. Cada uno de los objetos para insertar varios valores en él, y hacer que se autovalide.
EvilTeach
2
Solo tengo un montón de pares de nombre / valor en un archivo. No requiere objetos.
Bill the Lizard

Respuestas:

183

La forma de impulso (tm) :

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

La forma estándar de C ++ :

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

Nota : no olvides#include <sstream>

Johannes Schaub - litb
fuente
3
Creo que boost :: lexical_cast es la forma estándar de C ++, muy bien empaquetado para ti. Por cierto, litb, tienes un error tipográfico menor allí: "boot: lexical_cast".
Fred Larson
2
boost :: lexical_cast no es solo un simple contenedor alrededor del código de secuencia de cadena. Muchas de las rutinas de conversión se implementan en línea. De acuerdo con las mediciones de rendimiento en la parte inferior de esta página ( boost.org/doc/libs/1_47_0/libs/conversion/lexical_cast.htm ), boost :: lexical_cast es más rápido que el uso de cadenas y, en la mayoría de los casos, más rápido que scanf / printf
Ferruccio
1
@Ferr, ¿quién dijo que era una simple envoltura? Y gracias por proporcionar el enlace, en realidad hicieron pensar que era más o menos un contenedor simple :)
Johannes Schaub - litb
27
no te olvides #include <sstream>de la forma c ++ :)
VladL
3
En aras de la documentación, si no lo hace #include <sstream>, recibirá un error "no se permite el tipo incompleto".
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
fuente
1
Su forma C ++ no funcionará porque operator <<devuelve un en std::ostream&lugar de un stringstream&.
Konrad Rudolph el
Parece que mis cadenas están un poco oxidadas, prefiero las formas antiguas. Solucionado ahora (espero).
Adam Rosenfield
Tu código C me arrojó al principio. Todavía te voté por dar alternativas correctas.
Bill the Lizard el
2
voto a favor por incluir la forma C. me parece mucho más limpio.
Nealon
11
Votado a favor de la forma C ++ 11. Soy nuevo en C ++ y no me di cuenta de que había una to_stringfunción. Estoy usando Microsoft Visual C ++ 2013.
Trevor Sullivan
123

La forma estándar de C ++ 11 (si no le importa el formato de salida):

#include <string>

auto str = std::to_string(42.5); 

to_stringes una nueva función de biblioteca introducida en N1803 (r0), N1982 (r1) y N2408 (r2) " Acceso numérico simple ". También están losstod función para realizar la operación inversa.

Si desea tener un formato de salida diferente que "%f", use los métodos snprintfo ostringstreamcomo se ilustra en otras respuestas.

kennytm
fuente
3
Oh si bebé. to_string y stod ambos trabajan en Visual Studio 11.
BSalita
Oh querido bebé ... to_string no parece funcionar en VisualStudio 2010): Eso, o no sé lo que estoy haciendo (muy posible)
chessofnerd
1
¡Esto debería ser más alto, ya que es más moderno!
gsamaras
1
¿Hay alguna forma de hacer que esta función no agregue más decimales de los necesarios? Cuando convierto el doble 8.0, me da la cadena "8.000000", mientras "8"que estaría perfectamente bien.
HelloGoodbye
1
Esto no funciona para números pequeños ... por ejemplo: 1e-9 produce0.000000
user3728501
24

Si usa C ++, evítelo sprintf. No es C ++ y tiene varios problemas. Los Stringstreams son el método de elección, preferiblemente encapsulado como en Boost.LexicalCast que se puede hacer con bastante facilidad:

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
fuente
24

Puede usar std :: to_string en C ++ 11

double d = 3.0;
std::string str = std::to_string(d);
Yochai Timmer
fuente
Mis números eran realmente pequeños, y std::to_string()simplemente devolvieron 0.000000 y no en forma científica.
erfan
11

sprintfestá bien, pero en C ++, la forma mejor, más segura y también un poco más lenta de hacer la conversión es con stringstream:

#include <sstream>
#include <string>

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

También puedes usar Boost.LexicalCast :

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

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

En ambos casos, strdebe ser "453.23"posterior. LexicalCast tiene algunas ventajas, ya que garantiza que la transformación se complete. Utiliza stringstreams internamente.

coppro
fuente
10

Me gustaría ver el C ++ String Toolkit Libary . Acabo de publicar una respuesta similar en otro lugar. Lo he encontrado muy rápido y confiable.

#include <strtk.hpp>

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

El problema con lexical_cast es la incapacidad para definir la precisión. Normalmente, si está convirtiendo un doble en una cadena, es porque desea imprimirlo. Si la precisión es demasiado o muy poco, afectaría su salida.


fuente
4

Je, acabo de escribir esto (sin relación con esta pregunta):

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

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

Echa un vistazo sprintf()y familia.

Darron
fuente
2
Mencioné printf porque googleó apareció un montón de artículos que dicen que para convertir de un doble a una cadena usas printf. Asumen que lo único que podría estar haciendo es imprimir, que en mi caso es falso.
Bill the Lizard el
¿Por qué votas -1? Creo que sprintf es bueno. @BilltheLizard, sprint imprime algo en un char * no en la pantalla. Alguien respondió que el método c todavía tenía mucho voto.
Worldterminator
2

Normalmente para estas operaciones, debe usar las funciones ecvt, fcvt o 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 una función:

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

Podrías probar un estilo más 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
fuente
0

Uso to_string().
ejemplo:

#include <iostream>   
#include <string>  

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

  return 0;
}

ejecútelo usted mismo: http://ideone.com/7ejfaU
Estos también están disponibles:

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

Puedes convertir cualquier cosa a cualquier cosa usando esta función:

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
fuente