Pregunta

Hace poco leí una pregunta entrevista de trabajo de ejemplo:

Escribir la función de convertir un número entero en una cadena. Suponga que no tiene el acceso a funciones de biblioteca es decir, itoa (), etc ...

¿Cómo hacerlo?

¿Fue útil?

Solución

puñalada rápida en el que: (editado a números negativos mango)

int n = INT_MIN;
char buffer[50];
int i = 0;

bool isNeg = n<0;

unsigned int n1 = isNeg ? -n : n;

while(n1!=0)
{
    buffer[i++] = n1%10+'0';
    n1=n1/10;
}

if(isNeg)
    buffer[i++] = '-';

buffer[i] = '\0';

for(int t = 0; t < i/2; t++)
{
    buffer[t] ^= buffer[i-t-1];
    buffer[i-t-1] ^= buffer[t];
    buffer[t] ^= buffer[i-t-1];
}

if(n == 0)
{
    buffer[0] = '0';
    buffer[1] = '\0';
}   

printf(buffer);

Otros consejos

El algoritmo es fácil de ver en Inglés.

Dado un número entero, por ejemplo 123

  1. dividir por 10 => 123/10. Rendimiento, resultará = 12 y el resto = 3

  2. añadir 30h a 3 y empujar en la pila (añadiendo 30h convertirá 3 a la representación ASCII)

  3. repita el paso 1 hasta que el resultado <10

  4. añadir a 30h resultado y almacenar en la pila

  5. la pila contiene el número con el fin de | 1 | 2 | 3 | ...

Una mirada en la web para itoa aplicación le dará buenos ejemplos. Aquí está uno, evitando de revertir la cadena al final. Se basa en un buffer estático, así que tenga cuidado si vuelve a utilizar para diferentes valores.

char* itoa(int val, int base){

    static char buf[32] = {0};

    int i = 30;

    for(; val && i ; --i, val /= base)

        buf[i] = "0123456789abcdef"[val % base];

    return &buf[i+1];

}

Me habría que tener en cuenta que todos los caracteres son dígitos en orden creciente dentro del conjunto de caracteres ASCII y no tienen otros personajes entre ellos.

También sería utilizar los operadores / y the% repetidamente.

¿Cómo me gustaría ir sobre conseguir la memoria para la cadena dependería de la información no se ha dado.

Si se asume que es en decimal, entonces así:

   int num = ...;
   char res[MaxDigitCount];
   int len = 0;
   for(; num > 0; ++len)
   {
      res[len] = num%10+'0';
      num/=10; 
   }
   res[len] = 0; //null-terminating

   //now we need to reverse res
   for(int i = 0; i < len/2; ++i)
   {
       char c = res[i]; res[i] = res[len-i-1]; res[len-i-1] = c;
   }   

Una implementación de la función itoa() que parece una tarea fácil, pero en realidad hay que hacerse cargo de muchos aspectos que están relacionados en sus necesidades exactas. Supongo que en la entrevista que se espera para dar algunos detalles sobre su camino a la solución en lugar de copiar una solución que se puede encontrar en Google ( http://en.wikipedia.org/wiki/Itoa )

Aquí hay algunas preguntas que puede preguntarse a sí mismo o el entrevistador:

  • ¿Dónde se debe colocar la cadena (malloced? Pasa por el usuario? Variable estática?)
  • números de asistencia firmado debería?
  • ¿Debo Soporte de coma flotante?
  • ¿Debo otras bases de apoyo en lugar de 10?
  • ¿Necesitamos ninguna comprobación de entrada?
  • ¿Es la cadena de salida limitada en legth?

Y así sucesivamente.

Convertir entero en cadena sin acceso a bibliotecas

Convertir el dígito menos significativo a un personaje primero y luego proceder a dígitos más significativos.


Normalmente me gustaría cambiar el cadena resultante en su lugar, sin embargo, la recursividad permite saltarse ese paso con algo de código apretado.

Uso neg_a en myitoa_helper() evita un comportamiento indefinido con INT_MIN.

// Return character one past end of character digits.
static char *myitoa_helper(char *dest, int neg_a) {
  if (neg_a <= -10) {
    dest = myitoa_helper(dest, neg_a / 10);
  }
  *dest = (char) ('0' - neg_a % 10);
  return dest + 1;
}

char *myitoa(char *dest, int a) {
  if (a >= 0) {
    *myitoa_helper(dest, -a) = '\0';
  } else {
    *dest = '-';
    *myitoa_helper(dest + 1, a) = '\0';
  }
  return dest;
}

void myitoa_test(int a) {
  char s[100];
  memset(s, 'x', sizeof s);
  printf("%11d <%s>\n", a, myitoa(s, a));
}

Código y salida de prueba

#include "limits.h"
#include "stdio.h"

int main(void) {
  const int a[] = {INT_MIN, INT_MIN + 1, -42, -1, 0, 1, 2, 9, 10, 99, 100,
      INT_MAX - 1, INT_MAX};
  for (unsigned i = 0; i < sizeof a / sizeof a[0]; i++) {
    myitoa_test(a[i]);
  }
  return 0;
}

-2147483648 <-2147483648>
-2147483647 <-2147483647>
        -42 <-42>
         -1 <-1>
          0 <0>
          1 <1>
          2 <2>
          9 <9>
         10 <10>
         99 <99>
        100 <100>
 2147483646 <2147483646>
 2147483647 <2147483647>

Aquí hay un enfoque simple, pero sospecho que si a su vez en este estado en que está, sin entender y parafraseando él, su maestro sabrá que acaba de copiar fuera de la red:

char *pru(unsigned x, char *eob)
{
    do { *--eob = x%10; } while (x/=10);
    return eob;
}

char *pri(int x, char *eob)
{
    eob = fmtu(x<0?-x:x, eob);
    if (x<0) *--eob='-';
    return eob;
}

Varias mejoras son posibles, especialmente si quieres apoyar de manera eficiente más grande que la palabra entera de tamaños de hasta intmax_t. Lo dejo a usted para averiguar la forma en que estas funciones están destinadas a ser llamado.

Ligeramente más largo que la solución:

static char*
itoa(int n, char s[])
{
    int i, sign;

    if ((sign = n) < 0)  
        n = -n;        

    i = 0;

    do 
    {      
        s[i++] = n % 10 + '0';  
    } while ((n /= 10) > 0);   

    if (sign < 0)
        s[i++] = '-';

    s[i] = '\0';
    reverse(s);

    return s;
} 

Reverse:

int strlen(const char* str)
{
   int i = 0;
   while (str != '\0')
   {
       i++;
       str++;
   }

   return i;
}

static void
reverse(char s[])
{
    int i, j;
    char c;

    for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    }
}

Y aunque la decisión a largo davolno Aquí están algunas características útiles para los principiantes. Espero que sea útil.

El más rápido es el mejor?

unsigned int findDigits(long long x)
{
    int i = 1;
    while ((x /= 10) && ++i);
    return i;
}
// return the number of digits in x.
unsigned int digits(long long x)
{
    x < 0 ? x = -x : 0;
    return x < 10 ? 1 :
        x < 100 ? 2 :
        x < 1000 ? 3 :
        x < 10000 ? 4 :
        x < 100000 ? 5 :
        x < 1000000 ? 6 :
        x < 10000000 ? 7 :
        x < 100000000 ? 8 :
        x < 1000000000 ? 9 :
        x < 10000000000 ? 10 : findDigits(x);
}


char tochar(unsigned short from)
{
    return from == 0 ? '0' :
        from == 1 ? '1' : from == 1 ? '1' : from == 2 ? '2' :
        from == 3 ? '3' : from == 4 ? '4' : from == 5 ? '5' :
        from == 6 ? '6' : from == 7 ? '7' : from == 8 ? '8' :
        from == 9 ? '9' : '\0';
}

char * tostring(long long from)
{
    unsigned char negative = from < 0;
    unsigned int i = digits(from);
    char* to = (char*)calloc(1, i + negative);
    if (negative && (*to = '-') & (from = -from) & i++);
    *(to + i) = 0;
    while ((i>0+negative) && (*(to + (--i)) = tochar(((from) % 10))) | (from /= 10));
    return to;
}

Si desea depurar, puede dividir las condiciones (instrucciones) en
líneas de código dentro de {} el mientras alcances.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top