decimal a octal

Iniciado por Ander123, 27 Agosto 2012, 14:48 PM

0 Miembros y 1 Visitante están viendo este tema.

Ander123

Hola, como hago para decir que quiero que un numero x sea descompuesto entre potencias de ocho con un "do...while"

ecfisa

#1
Hola Ander123.

No entiendo muy bién lo que buscas pero a ver si esto te sirve...


#include <stdio.h>
#include <string.h>

/* Convierte numero en base 10 a base 2,3,..., N (probe hasta base 36) */
char *b10base_n(int num, unsigned char base) {
 char tmp[255], res[255];
 int mod, i, h=0;

 memset(tmp,'0',255);
 memset(res,'0',255);
 do {
   mod = num % base;
   num = num / base;
   if (mod < 10)
     tmp[h] = (char)mod + '0';
   else
     tmp[h] = (char)mod + '7';
   h++;
 } while (num > 0);
 tmp[h] = '\0';

 for(i=0; i < h; i++) res[i] = tmp[h-i-1];
 res[i] = '\0';

 return res;
}

/* Ejemplo de uso */
int main(int argc, char* argv[])
{
 int numero, base;
 printf("Numero en base 10: ");
 scanf("%d",&numero);
 printf("\nBase a la que convierte: ");
 scanf("%d",&base);
 printf("\n%d en base %d es: %s",numero,base, b10base_n(numero,base));

 while(getchar()!='\n');
 getchar();
 return 0;
}


Saludos.

fabianjsm

#2
Hola ecfisa. Estas retornando el puntero a una variable automatica! Si lo solucionas declarándola como estática sigues en problemas, porque este código fallaría:

char *a = b10base_n(100,10);
char *b = b10base_n(20,10);
printf("%s != %s\n", a, b);


A no ser que tomes siempre la precaución de copiar el dato después de cada llamada a la función b10base_n

char a[32], b[32];
strcpy(a, b10base_n(100,10));
strcpy(b, b10base_n(20,10));
printf("%s != %s\n", a, b);


Una de las soluciones podría ser reservar memoria con malloc o retornar haciendo return strdup(res), recordando liberar la memoria después. Por eso las funciones de este tipo en C trabajan con un puntero al buffer. En C++ retornas un std::string y problema resuelto.
El código no falla, esta haciendo lo que tú has programado, pero el resultado no es el deseado (error lógico)

ecfisa

Hola fabianjsm.

Entiendo lo que me comentas y llevas toda la razón, ¿ De este modo te parece mas correcto ?


char *base10basen(int num, unsigned char base) {
  char t1[255],t2[255];
  int mod, i, h=0;
  do {
    mod = num % base;
    num = num / base;
    if (mod < 10)
      t1[h] = (char)mod + '0';
    else
      t1[h] = (char)mod + '7';
    h++;
  } while (num > 0);
  t1[h] = '\0';

  for(i=0; i < h; i++) t2[i] = t1[h-i-1];
  t1[i] = '\0';
  return strdup(t1);
}

Pero no veo otra forma que liberar la memoria fuera de la función...

Y si, usando string es muchísimo más simple.

Saludos.



leosansan

Ander debes currrate el código antes, lo que tienes de código es "muy flojo", con muchos errores simples. Para que no te quedes en blanco te dejo el siguiente código. Por cierto, varian BASE a 2 puedes pasar a binario u otra base:
#include<stdio.h>
#define BASE      8
int   main()
{
   register int i=0,j,k =1;
   long long int n, N;
   printf ("Entre numero entero en base 10:\t"); scanf ("%lld",&N);
   n=N;
   while (n/BASE>=1)
       {
           n/=BASE; k++;
       }
   /*printf ("\nk =%d ",k);*/
   n=N;
   long long int digito[k];
   while (n/BASE>=1)
       {
           digito[i] = n%BASE;
           n/=BASE; i++;
       }
   digito[i] = n%BASE;
   printf ("\n%lld (en base %d) es igual a :  ",N,BASE);
   for( j=i ; j>=0 ;j-- ) printf ("%lld",digito[j]);
   puts  ("\n");
   return 0;
}

Puedes comprobar la conversion en la siguiente página:
http://es.ncalculators.com/digital-computation/decimal-octal-converter.htm

fabianjsm

#5
La memoria debe ser liberada con free (incluso en C++, a no ser que modifiques tu función para que reserve memoria con new), strdup hace esto (copy paste de la libreria):

Código (cpp) [Seleccionar]
char *strdup (const char *s)
{
   char *d = malloc (strlen (s) + 1);
   if (d != NULL)
       strcpy (d,s);
   return d;
}


Una alternativa elegante (en la librería GNU C) es strdupa (y strndupa), similar a strdup pero que asigna memoria en la pila, esto hace que no sea necesario liberar la memoria, ya que esta es liberado automáticamente al salir de la función que invocó a strdupa. Funciona sin problemas en C++, y por contraparte debes recordar no liberar la memoria ;-)

Cita de: leosansan en 30 Agosto 2012, 15:19 PMAnder debes currrate el código antes

Muy cierto, haber si nos muestras algún adelanto Ander123!

ecfisa

#6
Hola fabianjsm.
CitarLa memoria debe ser liberada con free (incluso en C++)
Obviamente, eso está fuera de toda duda. Pero me refería a que no encontre modo de liberar la memoria  no siendo fuera de la función.

Por ejemplo:

...
char *base10basen(int num, unsigned char base) {
 char t1[255],t2[255];
 int mod, i, h=0;
 do {
   mod = num % base;
   num = num / base;
   if (mod < 10)
     t1[h] = (char)mod + '0';
   else
     t1[h] = (char)mod + '7';
   h++;
 } while (num > 0);
 t1[h] = '\0';

 for(i=0; i < h; i++) t2[i] = t1[h-i-1];
 t1[i] = '\0';
 return strdup(t1);
}

int main() {
char *a[10];
 int i;

 for(i=0; i < 10; i++) a[i] = base10basen(i*10,16);
 for(i=0; i < 10; i++) printf("%s\n",a[i]);
 for(i=0; i < 10; i++) free(a[i]);
 ...
}

La memoria se reserva en el heap ya que si se haciera en el stack el valor se perdería al retornar de la función.

Es decir que no encuentro forma de encapsular la reserva/liberación de la memoria dentro de la función, ya que si se libera antes de return es claro que devuelve cualquier cosa y despues de él no tiene efecto...


Saludos.