• Viernes 11 de Octubre de 2024, 14:47

Autor Tema:  convertir un int en char*  (Leído 3494 veces)

MindEye

  • Miembro MUY activo
  • ***
  • Mensajes: 185
    • Ver Perfil
convertir un int en char*
« en: Sábado 23 de Julio de 2011, 11:25 »
0
- Buenos días, soy nuevo con c++, estoy usando el compilador gcc y programando con geany. El problema es que no se como hace para poder meter un entero en una char*.

- Todo viene porque tengo un metodo que quiero que me calcule la máscara de una red, pero cuando hace el calculo del número que corresponde, no puedo concatenarlo con la cadena que ya tengo calculada, es que cuando el valor es cero pongo directamente cero en la cadena, y cuando es mayor de 8 pongo el 255, ahora, como sea un valor intermedio y necesite calcular, plufff, me da violación del segmento al intentar concatenarlo.

- Gracias.

ProfesorX

  • Moderador
  • ******
  • Mensajes: 796
  • Nacionalidad: mx
    • Ver Perfil
Re:convertir un int en char*
« Respuesta #1 en: Sábado 23 de Julio de 2011, 15:55 »
0
Hola MindEye, bienvenido al foro :)

Deberias publicar tu codigo, para ver que estas haciendo mal, porque asi es como estar adivinando :P

Aun asi, de manera rapida y por lo que menciones, el error de Violacion de semento (segment fault) ocurre cuando sobreescribes la memoria, esto ocurre por un mal manejo de punteros, y/o arrays.

Probablemente al concatenar el arreglo, estas usando un arreglo que no tiene el tamaño suficiente para guardar tu cadena concatenada, entonces como no tiene el tamaño suficiente, se sobreescribe la memoriia y viene el segment fault.

Una direccion IP, que ocupe todo sus digitos como la siguiente: 255.255.255.255, tiene una longitud de 15 caracteres (incluyendo los puntos), por lo tanto, debes definir un arreglo con un tamaño minimo de 16, ya que ademas, las cadenas requieren espacio para un caracter adicional, puesto que todas llevan el caracter nulo '\0' para indicar el final de la cadena.

Por lo tanto al definir tu variable para la direccion IP si utilizas arreglos quedaria asi:

Código: [Seleccionar]
char direccion_ip[16];

Si utilizas memoria dinamica y punteros:

Código: [Seleccionar]
char *direccion_ip = (char*) malloc(sizeof(char)*16);

Si eso no corrige tu codigo, publica lo que haces para ver donde esta el error.

Saludos :)

NOTA:
==================================================================
Este foro es para ayudar, aprender, compartir... usenlo para eso,
NO SE RESUELVEN DUDAS POR MENSAJE PRIVADO Y MENOS POR CORREO
==================================================================

MindEye

  • Miembro MUY activo
  • ***
  • Mensajes: 185
    • Ver Perfil
Re:convertir un int en char*
« Respuesta #2 en: Sábado 23 de Julio de 2011, 16:53 »
0
- Tienes razón, aquí pongo el código con lo que estoy intentando hacer:

char * ipmask::calcularMascara(int ntipo)
{
   char *mask, *nmask, *punto;
   mask = new char[16]; // la cadena más grande que podemos tener es 255.255.255.255 más el carácter fin
   nmask="255."; punto="";
   int num = 255;
   int signed desplaza=0;
   int unsigned nnum=0;
   while (ntipo>=0)
   {
      strcat(mask,punto);
      punto=".";
      if (ntipo>8)
      {
         strcat(mask,"255");
         ntipo=ntipo-8;
      }
      else
      {
         desplaza = (8-ntipo);
         if (desplaza==0 || ntipo==0)
         {
            nmask=(char*)"000";
         }
         else
         {
            nnum = ntipo<<desplaza;
            nmask = ((char*)nnum);
         }
         ntipo=ntipo-8;
         strcat(mask,nmask); // Aquí se la pega
      }
   }   
        return mask;
}

PD. Gracias por la bienvenida ProfesorX

ProfesorX

  • Moderador
  • ******
  • Mensajes: 796
  • Nacionalidad: mx
    • Ver Perfil
Re:convertir un int en char*
« Respuesta #3 en: Domingo 24 de Julio de 2011, 08:04 »
0
Hola de nuevo, disculpa la tardanza en publicar mi respuesta, pero pues el trabajo es primero :P

Revise tu codigo y si, como te dije antes, estas haciendo mal uso de los punteros, eso es muy comun.

Mucha gente cree que es correcto hacer algo como

Código: [Seleccionar]
char *nmask;
nmask="255."

Sin comprender exactamente que hacen esas lineas.

Lo que estas haciendo ahi es crear un puntero a char, y luego hacer que apunte a una direccion de memoria que contiene un valor de cadena constante. Mientras no quieras cambiar el contenido de esa cadena todo ira bien, pero si por algun motivo deseas modificar ese contenido, por ejemplo en tu caso concatenando, inmediatamente estaras sobrescribiendo la memoria con los consecuentes errores.

Lo correcto es lo siguiente:
Código: [Seleccionar]
char *nmask = new char[5];
strncpy(nmask, "255.", 5);

Aun asi deberas estar al pendiente de no sobrepasar el tamaño de tu memoria dinamica, en este caso 5.

En muches lenguajes las cadenas se manejan de manera diferente y si es valido hacer algo como nmask = "255." e incluso nmask = "255." + "255" (concatenacion)

El lenguaje C++ si permite asignacion de cadenas con = y concatenacion con +, pero para eso debes usar la clase string. que maneja las cadenas por medio de una clase, y tiene operadores y metodos especiales para manejarlas, pero eso ya es otra historia.

El otro error de tu codigo es que cuando usas new char[] asumes que la memoria que obtienes esta limpia (o sea con valor cero) y eso no es asi. Entonces dado que usas strcat, estas concatenando el contenido de basura de tu variable con el valor deseado y si la variable contiene 5 valores basura, y le concatenas 16 mas, obtienes 21, pero el tamaño maximo es de 16 asi que de nuevo sobreescribes la memoria y de nuevo viene el segfault.

Lo correcto seria borrar completamente el contenido de la memoria, esto lo puedes hacer por medio de un ciclo o de manera rapida usando memset.

Dicho eso, te dejo el codigo con correcciones y anotaciones, lo probe y ya no da segment fault, pero sin embargo me parece que no esta correcto aun, la logica para obtener la mascara al parecer esta mal, pero creo que con los consejos que te doy, podras terminarlo tu solo ;)

Código: [Seleccionar]
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;

char * calcularMascara(int ntipo)
{
    char *mask, *nmask, *punto;
    mask = new char[16]; // la cadena más grande que podemos tener es 255.255.255.255 más el carácter fin
    nmask = new char[5];
    punto = new char[2];

    // manera incorrecta de asignar un valor a un char* o char[],
    // debes usar strcpy o strncpy
    //nmask="255."; punto="";
    // Lo mas correcto es borrar la memoria antes de que concatenes
    // de esa manera evitas concatenar con valores basura.
    // Para borrar de manera rapida la memoria dinamica se usa memset
    // Aqui para borrar podrias usar tambien strncpy(mask, "", 2);
    memset(mask, 0, sizeof(char)*16);
    memset(punto, 0, sizeof(char)*2);
    strncpy(nmask, "255.", 5);
    int num = 255;
    int signed desplaza=0;
    int unsigned nnum=0;
    while (ntipo>=0)
    {
        strcat(mask,punto);
        //punto=".";
        strncpy(punto, ".", 2);
        if (ntipo>8)
        {
            strcat(mask,"255");
            ntipo=ntipo-8;
        }
        else
        {
            desplaza = (8-ntipo);
            if (desplaza==0 || ntipo==0)
            {
                //nmask=(char*)"000";
                strncpy(nmask, "000", 4);
            }
            else
            {
                nnum = ntipo<<desplaza;
                // Manera incorrecta de convertir un int a char
                // para eso puedes usar sprintf() (portable)
                // o itoa() (no portable, pues no es funcion estandard)
                //nmask = ((char*)nnum);
                sprintf(nmask, "%d", nnum);
            }
            ntipo=ntipo-8;
            strcat(mask,nmask); // Aquí se la pega
        }
    }

    // recuerda liberar tu memoria dinamica cuando ya no la necesites.
    // No libero mask, porque es el puntero que regresa la funcion
    // pero debes liberarlo afuera.
    delete nmask;
    delete punto;

    return mask;
}

int main()
{
    char *mascara;
    // Aqui ya no es necesario usar new o malloc pues dentro de la funcion
    // ya lo estas usando para el puntero que regresas, pero despues de
    // que lo termines de ocupar liberalo.
    for (int i = 1; i < 32; i++)
    {
        mascara = calcularMascara(i);

        printf("%s\n", mascara);
        delete mascara;
    }

    return 0;
}

Saludos y  :suerte:

NOTA:
==================================================================
Este foro es para ayudar, aprender, compartir... usenlo para eso,
NO SE RESUELVEN DUDAS POR MENSAJE PRIVADO Y MENOS POR CORREO
==================================================================

MindEye

  • Miembro MUY activo
  • ***
  • Mensajes: 185
    • Ver Perfil
Re:convertir un int en char*
« Respuesta #4 en: Lunes 25 de Julio de 2011, 08:38 »
0
- Muchisimas gracias profesorX, no sólo me ha ayudado con este problema si que además me ha enseñado algunas cosas nuevas.

- Muchas gracias.

ProfesorX

  • Moderador
  • ******
  • Mensajes: 796
  • Nacionalidad: mx
    • Ver Perfil
Re:convertir un int en char*
« Respuesta #5 en: Lunes 25 de Julio de 2011, 16:10 »
0
Me alegra que te haya servido.

Bueno, se que probablemente ya lo terminaste, pero como ejercicio hice mi propia funcion para calcular la mascara, esta mas simplificada, y utiliza el operador << (corrimiento de bits a la izquierda) para calcular el valor, y sprintf para convertirlo a cadena, la dejo para ti y para quien en el futuro le pueda servir, estudiala y analizala.

Código: [Seleccionar]
#include <cstdio>

char *calcularMascara(int ntipo)
{
    char *mask = new char[16];
    int a, b, c, d;
    a = b = c = d = 0;

    for (int i = 1; i <= ntipo; i++)
    {
        if (i <= 8)
            a = a + (1 << (8-i));
        else
            if (i <= 16)
                b = b + (1 << (16-i));
            else
                if (i <= 24)
                    c = c + (1 << (24-i));
                else
                    if (i <= 32)
                        d = d + (1 << (32-i));
    }

    sprintf(mask, "%03d.%03d.%03d.%03d", a, b, c, d);

    return mask;
}

int main()
{
    char *mascara;

    for (int i = 1; i <= 32; i++)
    {
        mascara = calcularMascara(i);
        printf("%s\n", mascara);

        delete mascara;
    }

    return 0;
}

Saudos :)
« última modificación: Lunes 25 de Julio de 2011, 16:19 por ProfesorX »

NOTA:
==================================================================
Este foro es para ayudar, aprender, compartir... usenlo para eso,
NO SE RESUELVEN DUDAS POR MENSAJE PRIVADO Y MENOS POR CORREO
==================================================================

MindEye

  • Miembro MUY activo
  • ***
  • Mensajes: 185
    • Ver Perfil
Re:convertir un int en char*
« Respuesta #6 en: Martes 26 de Julio de 2011, 02:13 »
0
- Muchísimas gracias profesorX, gracias a tus indicaciones, no solo termine la función sino que además he aprendido algo nuevo.

- Hasta la próxima profesorX.