1

Tengo una variable de tipo double: double p = 32.121; y deseo guardarlo en otra variable de tipo char[8]: char j[8]= "";.

Estoy trabajando con con VC++ 2008 y C++9.

He intentado con la funcionalidad propia de c++. Hasta aqui he llegado y el codigo es correcto pero devuelve dos veces el valor.

std::string ConvertDoubleToString(double value){
std::stringstream ss;
ss << value;
return ss.str();}

int _tmain(){

double i = 32.987;

    std::string str = ConvertDoubleToString(i);
    cout<<str;

    // ahora lo almacenanos en un char[]
    char j[8];
    strcpy(j,str.c_str());
    std::cout << j;
    Sleep(10000);
    return 0;
}
Adriana Hernández
  • 1,606
  • 1
  • 15
  • 31
Andermutu
  • 67
  • 13
  • Una pregunta tonta ¿Qué es C++9? Y para decir que no te devuelve nada... ¿Qué valor tiene `i`? ¿Dónde está declarada? ¿y definida? – eferion Jul 04 '17 at 10:13
  • La version de c++ que uso. – Andermutu Jul 04 '17 at 10:20
  • Esa versión de C++ no existe... [wiki](https://en.wikipedia.org/wiki/C%2B%2B). Me podría valer C++98, C++03, C++11, C++14 o C++17 (fíjate que todas tienen dos dígitos) – eferion Jul 04 '17 at 10:21
  • A ver, la pregunta no es como una pizarra donde vas modificando a tu antojo las condiciones... ¿Te has molestado siquiera en leer las respuestas y sus comentarios? Estás eligiendo una solución que **no funciona** simplemente porque está haciendo una copia binaria y no una conversión. Tienes que usar `stringstream`, `ostringstream`, `sprintf`, o alguna de sus variantes... ¿Por qué piensas que aplicar una respuesta con puntuación negativa es buena idea? – eferion Jul 04 '17 at 10:45
  • yo no he aplicado ninguna resouesta como negativa, todo lo contrario os estoy eternamente agradecido. – Andermutu Jul 04 '17 at 10:46
  • Tu no... pero esto es una comunidad y todos podemos votar... las respuestas erróneas se acaban puntuando negativamente por alguna razón – eferion Jul 04 '17 at 10:46
  • solo queria hacer saber que el codigo no funcionaba, no era mi intencion que hubiera votos negativos... – Andermutu Jul 04 '17 at 10:48
  • Los votos negativos en la respuesta no son responsabilidad tuya. Si alguien responde algo que no es correcto se le castiga con puntos negativos y conforme el aporte es más relevante consigue puntos positivos... así funciona la reputación en StackOverflow – eferion Jul 04 '17 at 10:49

4 Answers4

3

Puedes optar por hacerlo a la vieja usanza de C

double p = 32.121;
char j[8];

sprintf(j,"%f",p);

O puedes hacer uso de funionalidad propia de C++:

std::stringstream stream;
stream << p;

strcpy(j,p.str().c_str());

Aunque si no es requisito imprescindible almacenarlo en un char[8] lo más recomendable es usar std::string:

double p = 32.121;

std::stringstream stream;
stream << p;

std::string j = p.str();
std::cout << j;

Se ha actualizado la pregunta: edito

const char* ConvertDoubleToString(double value)
{
  std::stringstream ss;
  ss << value;
  const char * str = ss.str().c_str();
  return str;
}

int _tmain()
{
  const char* j=ConvertDoubleToString(i);
  cout<<j;
  Sleep(4000);
  return 0;
}

¿Qué sucede aquí?

veamos...

  const char * str = ss.str().c_str();

Ahí estás retornando un puntero a una estructura interna de un objeto temporal:

  • ss.str() crea un objeto std::string temporal
  • [string].c_str() expone el buffer interno del string
  • después de esa línea el string se destruye y su puntero interno deja de ser válido

Es decir, lo almacenado en str ya no debe usarse.

¿Solución?

Devuelve un string:

std::string ConvertDoubleToString(double value)
{
  std::stringstream ss;
  ss << value;
  return ss.str();
}

int _tmain()
{
  std::string str = ConvertDoubleToString(i);
  cout<<str;

  // ahora lo almacenanos en un char[]
  char j[8];
  strcpy(j,str.c_str());
  std::cout << j;
  Sleep(4000);
  return 0;
}
eferion
  • 49,291
  • 5
  • 30
  • 72
  • Gracias. H eprobado con la funcionalidad propia de c++ pero me salen dos errores; alguna idea? – Andermutu Jul 04 '17 at 10:19
  • @Andermutu no tengo la bola de cristal aquí para adivinar los errores. El código funciona así que posiblemente te falten includes – eferion Jul 04 '17 at 10:23
  • Eferion confio totalmente que tu codigo funciona y lo he probado pero por ejemplo pero pasa esto `double i = 32.987` lo que me devuelve el codigo es 32.98732.987 alguna idea? – Andermutu Jul 04 '17 at 10:50
  • @Andermutu eso es porque los decimales y el binario no se llevan todo lo bien que nos gustaría. Echa un vistazo a [este enlace](https://es.stackoverflow.com/questions/197/por-qu%c3%a9-mis-programas-no-pueden-hacer-c%c3%a1lculos-aritm%c3%a9ticos-correctamente) – eferion Jul 04 '17 at 10:55
  • Gracias, ahora lo miro. – Andermutu Jul 04 '17 at 10:57
1

Si quieres hacer la conversión en modo texto, tienes múltiples opciones. La más propia de C++ es utilizar el stream de cadenas, o stringstream. La idea es introducir datos en un stream, tal y como se haría con, por ejemplo, cout, y obtener una cadena de texto. Para ello, necesitaremos un stringstream de salida, es decir, un ostringstream. Estas clases están en la cabecera sstream.

ostringstream cnvt;

cnvt << 32.121;
cout << cnvt.str() << endl;

Si quieres hacer la conversión binaria, puedes hacerlo de dos maneras, las dos "a la antigua":

Copia el contenido de la memoria de uno en otro:

char bytes[sizeof(double)];
double x = 32.121;

// Copying memory
memcpy( bytes, &x, sizeof(x) );

for(int i = 0; i < sizeof( x ); ++i) {
    cout << bytes[ i ] << ' ';  
}

Al copiar desde el inicio de x (&x), el número de bytes que ocupa x (sizeof(x)), te aseguras de estar copiando el contenido entero de la variable. El array de destino debe tener el mismo tamaño, claro.

Utiliza una union

Las union casi no se usan hoy en día, si bien para este caso encajan como un guante. Todos los miembros de una union comienzan en la misma dirección de memoria, por lo que al modificar uno de ellos, los estás modificando todos a la vez.

union Conversor {
    char bytes[sizeof( double )];
    double x;
};

Así, la modificar Conversor.x, obtenemos el valor convenientemente descompuesto en Conversor.bytes.

Conversor cnvt;
cnvt.x = 32.121;;

for(int i = 0; i < sizeof( x ); ++i) {
    cout << cnvt.bytes[ i ] << ' '; 
}

Tienes el código completo en IDEOne.

Baltasarq
  • 1,084
  • 8
  • 11
  • Quiere hacer un ToString... no almacenar la secuencia binaria de un double en un buffer de tipo char... – eferion Jul 04 '17 at 10:20
  • Lo había entendido mal, entonces. Modificaré la pregunta para abarcar el caso de la conversión a texto. – Baltasarq Jul 04 '17 at 10:22
  • Ok. Cuando esté arreglado avísame para revisar el negativo ;) – eferion Jul 04 '17 at 10:22
  • Hecho, añadida la conversión de texto. – Baltasarq Jul 04 '17 at 10:26
  • Considera eliminar el contenido de la primera respuesta ya que es claramente erróneo y puede llevar a confusiones – eferion Jul 04 '17 at 10:29
  • Gracias ahora lo miro, para utilizar el modo union tambien tengo que añadir al codigo esto ? `ostringstream cnvt; cnvt << 32.121; cout << cnvt.str() << endl;` – Andermutu Jul 04 '17 at 10:29
  • No; para utilizar la union no necesitas emplear nada más. Pero recuerda que la conversión con ostringstream es en modo texto, mientras que con union o memcpy utilizas la conversión binaria. – Baltasarq Jul 04 '17 at 10:32
  • Eso y que la conversión binaria con `union` está mal hecha... – eferion Jul 04 '17 at 10:45
  • Los que han respondido a una pregunta no deberían poder hacer comentarios en otras respuestas de la mismas pregunta... de acuerdo, @eferion, ya que has dejado un halo de misterio sobre el tema (supongo que a propósito), ¿por qué está mal hecha la conversión con union? – Baltasarq Jul 04 '17 at 10:49
  • porque debería ser `for(int i=0; i – eferion Jul 04 '17 at 11:07
  • El código fuente está enlazado en la respuesta, podías haberlo mirado; te habrías dado cuenta de que *x* es la variable que se toma como "entrada", y que, por supuesto, el código compila. En cuanto a lo que incluya o no mi respuesta, aún respetando tu opinión, prefiero decidirlo yo. E insisto en que los comentarios de los autores de otras respuestas, en su afán por restar puntos a otros, provocan "confusiones" de este tipo. Por favor, déjalo ya. – Baltasarq Jul 04 '17 at 11:29
  • La reputación me importa lo mismo que saber si los virus de la gripe son rojos o morados. Lo que si me importa es mantener la etiqueta de C++ limpia y organizada y las respuestas que no tienen nada que ver con lo preguntado lo lógico es quitarlas ya que no aportan valor. Efectivamente tu decides lo que pones en tu respuesta... pero no olvides que es la comunidad la que decide si tu contenido merece estar en SO o no (ojo la comunidad, no yo) o si su respuesta merece puntuación positiva o negativa... te lo he dicho en el primer comentario... deja una respuesta que sea buena y quito el negativo – eferion Jul 04 '17 at 11:45
  • [Continuemos el debate en el chat](http://chat.stackexchange.com/rooms/61543/discussion-between-eferion-and-baltasarq). – eferion Jul 04 '17 at 11:45
0

Siempre que puedas alguna version de C++ 11 o en superior es preferible usar to_string() que facilita el trabajo y sin la necesidad de crear una propia implementacion.

int main()
{

    double real = 32.121;

    string sResult = std::to_string(real);
    cout<<sResult<<endl;

    return 0;
}
JGarnica
  • 1,477
  • 3
  • 11
  • 20
-1

Buenas,

Prueba con esto:

double a=32.121;
char arr[sizeof(a)];
memcpy(arr,&a,sizeof(a));

Espero que te sirva de ayuda.

Marc
  • 5,005
  • 7
  • 17
  • 36
  • Esto posiblemente cause algunos pitidos y símbolos extraños si lo intenta imprimir... creo que Andermutu quiere la representación en texto del número no su representación binaria en un arreglo. – PaperBirdMaster Jul 04 '17 at 10:19
  • Gracias por la ayuda pero lo uico que devuelve este codigo son simbolos extraños. – Andermutu Jul 04 '17 at 10:27
  • @Marc Puig lee algo sobre el código ascii y como funciona un `char`, estas muy herrado en la lógica en la que funciona el lenguaje. – MindLerp Jul 07 '17 at 11:15