¿Cómo puedo convertir un int en una cadena en C?

8 minutos de lectura

avatar de usuario de user1063999
usuario1063999

¿Cómo se convierte un int (entero) a una cadena?

Estoy tratando de hacer una función que convierta los datos de un struct en una cadena para guardarlo en un archivo.

  • printf o uno de sus primos debería hacer el truco

    – pmg

    24 de noviembre de 2011 a las 13:21

  • posible duplicado de ¿Dónde está la función itoa en Linux?

    – Pablo R.

    24 de noviembre de 2011 a las 13:27

  • es posible que también desee ver estas preguntas frecuentes sobre la serialización, y tal vez las siguientes preguntas relacionadas con la serialización en C: (a), (b), (c) para lograr su intención real.

    – mooooooooooooooooooooooo

    24 de noviembre de 2011 a las 13:35


  • Mi molestia semántica favorita habitual aquí. No quieres convertir nada; desea obtener una cadena que contenga una representación (¿base 10?) del valor de la int. Si lo se. Es un atajo muy común, pero todavía me molesta.

    – dmckee — gatito ex-moderador

    24 de mayo de 2014 a las 2:41

  • ¿Puede rechazar la respuesta aceptada actual y aceptar la más votada? itoa no es estándar, por lo que snprintf es más portátil.

    – SS Ana

    24 de enero de 2020 a las 22:43

avatar de usuario de cnicutar
cnicutar

Puedes usar sprintf hacerlo, o tal vez snprintf si lo tienes:

char str[ENOUGH];
sprintf(str, "%d", 42);

Donde el número de caracteres (más el carácter de terminación) en el str se puede calcular usando:

(int)((ceil(log10(num))+1)*sizeof(char))

  • Para estar seguro ENOUGH es suficiente podemos hacerlo por malloc(sizeof(char)*(int)log10(num))

    – Hauleth

    24 de noviembre de 2011 a las 13:25

  • @Hauleth O incluso +2, considerando que (int)log10(42) es 1.

    – Christian Raú

    24 de noviembre de 2011 a las 13:34


  • O puede calcularlo en tiempo de compilación: #define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)

    – café

    25 de noviembre de 2011 a las 0:31

  • @hauleth Still +2 en lugar de +1, incluso con ceil: ceil(log(100)) = 2.0, no 3. Así que +1 para las potencias exactas de 10, y otro +1 para terminar nulo.

    – no-solo-yeti

    12 de febrero de 2015 a las 17:23

  • No tiene en cuenta el signo menos y la configuración regional: separador de miles y agrupación. Por favor, hazlo de esta manera: usa int length = snprintf(NULL, 0,"%d",42); para obtener longitud, y luego asignar length+1 caracteres para la cadena.

    – usuario2622016

    28 de septiembre de 2015 a las 6:10

Avatar de usuario de Alexander Galkin
Alejandro Galkin

Como se señaló en un comentario, itoa() no es un estándar, ¡así que mejor use el enfoque sprintf() sugerido en la respuesta rival!


Puedes usar el itoa() función a convertir su valor entero a una cadena.

Aquí hay un ejemplo:

int num = 321;
char snum[5];

// Convert 123 to string [buf]
itoa(num, snum, 10);

// Print our string
printf("%s\n", snum);

Si desea generar su estructura en un archivo, no es necesario convertir ningún valor de antemano. Solo puedes usar el especificación de formato printf para indicar cómo generar sus valores y usar cualquiera de los operadores de familia printf para generar sus datos.

  • itoa no es estándar; consulte, por ejemplo, stackoverflow.com/questions/190229/…

    – Pablo R.

    24 de noviembre de 2011 a las 13:26

  • @SeanRamey Esto itoa() sufre el mismo potencial de desbordamiento de búfer que gets().

    – chux – Reincorporar a Monica

    1 sep 2018 a las 15:55

  • itoa no está disponible en C (al menos C99). está más disponible en C++

    –Motti Shneor

    27 de marzo de 2019 a las 6:43

  • Cómo conseguir esto sin sprintf o itoa? ¿Posiblemente mientras escribe una biblioteca estándar personalizada?

    – SS Ana

    30 de marzo de 2019 a las 2:28

  • ¿Por qué pasaste el argumento como 10?

    – Rasathurai Karan

    8 sep 2021 a las 11:53

avatar de usuario de user2622016
usuario2622016

La respuesta corta es:

snprintf( str, size, "%d", x );

Cuanto más largo es: primero debe averiguar el tamaño suficiente. snprintf te dice la longitud si lo llamas con NULL, 0 como primeros parámetros:

snprintf( NULL, 0, "%d", x );

Asigne un carácter más para el terminador nulo.

#include <stdio.h> 
#include <stdlib.h>

int x = -42;
int length = snprintf( NULL, 0, "%d", x );
char* str = malloc( length + 1 );
snprintf( str, length + 1, "%d", x );
...
free(str);

Si funciona para cada cadena de formato, puede convertir flotante o doble en cadena usando "%g"puede convertir int a hexadecimal usando "%x"etcétera.

  • #incluye #incluye

    – usuario1821961

    2 de noviembre de 2017 a las 19:29


  • @ user1821961 Gracias, realmente debería mencionarse que estos archivos de encabezado deben incluirse.

    – byxor

    27 de abril de 2018 a las 19:49

  • oye, sé que esta es una respuesta muy antigua, pero ¿por qué “+1” en malloc? ¿Es para el ‘\0’?

    – Ballena_voladora

    3 abr 2021 a las 14:34

  • Sí, +1 es para el ‘\0’. snprintf devuelve la longitud sin contar el carácter nulo de terminación, pero en el segundo parámetro espera la longitud con el carácter nulo de terminación, por lo que la longitud + 1.

    – usuario2622016

    3 abr 2021 a las 19:33

  • @jinkwon Sí stackoverflow.com/a/35036037/330457

    – Jin Kwon

    23 de septiembre de 2021 a las 14:22

Avatar de usuario de David C. Rankin
David C Rankin

Después de haber examinado varias versiones de itoa para gcc, la versión más flexible que he encontrado que es capaz de manejar conversiones a binario, decimal y hexadecimal, tanto positivo como negativo, es la cuarta versión que se encuentra en http://www.strudel.org.uk/itoa/. Mientras sprintf/snprintf tienen ventajas, no manejarán números negativos para otra cosa que no sea la conversión decimal. Dado que el enlace anterior está fuera de línea o ya no está activo, he incluido su cuarta versión a continuación:

/**
 * C++ version 0.4 char* style "itoa":
 * Written by Lukás Chmela
 * Released under GPLv3.
 */
char* itoa(int value, char* result, int base) {
    // check that the base if valid
    if (base < 2 || base > 36) { *result="\0"; return result; }

    char* ptr = result, *ptr1 = result, tmp_char;
    int tmp_value;

    do {
        tmp_value = value;
        value /= base;
        *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
    } while ( value );

    // Apply negative sign
    if (tmp_value < 0) *ptr++ = '-';
    *ptr-- = '\0';
    while(ptr1 < ptr) {
        tmp_char = *ptr;
        *ptr--= *ptr1;
        *ptr1++ = tmp_char;
    }
    return result;
}

avatar de usuario de catfood
comida de gato

Aquí hay otra forma.

#include <stdio.h>

#define atoa(x) #x

int main(int argc, char *argv[])
{
    char *string = atoa(1234567890);
    printf("%s\n", string);
    return 0;
}

  • Funciona solo para constantes, no para variables.

    – Desnudo

    3 de febrero de 2014 a las 22:06

  • ¿Por qué no funciona si pongo una macro ahí…? ¿No es una constante también?

    – Edu590

    5 de febrero de 2022 a las 15:39

Convertir cualquier cosa en una cadena debe 1) asignar la cadena resultante o 2) pasar en un char * destino y tamaño. Ejemplo de código a continuación:

Ambos funcionan para todos int incluido INT_MIN. Proporcionan una salida consistente a diferencia de snprintf() que depende de la configuración regional actual.

Método 1: Devoluciones NULL en memoria insuficiente.

#define INT_DECIMAL_STRING_SIZE(int_type) ((CHAR_BIT*sizeof(int_type)-1)*10/33+3)

char *int_to_string_alloc(int x) {
  int i = x;
  char buf[INT_DECIMAL_STRING_SIZE(int)];
  char *p = &buf[sizeof buf] - 1;
  *p = '\0';
  if (i >= 0) {
    i = -i;
  }
  do {
    p--;
    *p = (char) ('0' - i % 10);
    i /= 10;
  } while (i);
  if (x < 0) {
    p--;
    *p = '-';
  }
  size_t len = (size_t) (&buf[sizeof buf] - p);
  char *s = malloc(len);
  if (s) {
    memcpy(s, p, len);
  }
  return s;
}

Método 2: Vuelve NULL si el búfer era demasiado pequeño.

static char *int_to_string_helper(char *dest, size_t n, int x) {
  if (n == 0) {
    return NULL;
  }
  if (x <= -10) {
    dest = int_to_string_helper(dest, n - 1, x / 10);
    if (dest == NULL) return NULL;
  }
  *dest = (char) ('0' - x % 10);
  return dest + 1;
}

char *int_to_string(char *dest, size_t n, int x) {
  char *p = dest;
  if (n == 0) {
    return NULL;
  }
  n--;
  if (x < 0) {
    if (n == 0) return NULL;
    n--;
    *p++ = '-';
  } else {
    x = -x;
  }
  p = int_to_string_helper(p, n, x);
  if (p == NULL) return NULL;
  *p = 0;
  return dest;
}

[Edit] a petición de @Alter Mann

(CHAR_BIT*sizeof(int_type)-1)*10/33+3 es al menos el número máximo de char necesario para codificar algún tipo de entero con signo como una cadena que consta de un signo negativo opcional, dígitos y un carácter nulo.

El número de bits sin signo en un entero con signo no es mayor que CHAR_BIT*sizeof(int_type)-1. Una representación en base 10 de un n-bit número binario toma hasta n*log10(2) + 1 dígitos 10/33 es un poco más que log10(2). +1 por el signo char y +1 para el carácter nulo. Se podrían usar otras fracciones como 28/93.


Método 3: si uno quiere vivir al límite y el desbordamiento del búfer no es una preocupación, sigue una solución simple C99 o posterior que maneja todo int.

#include <limits.h>
#include <stdio.h>

static char *itoa_simple_helper(char *dest, int i) {
  if (i <= -10) {
    dest = itoa_simple_helper(dest, i/10);
  }
  *dest++ = '0' - i%10;
  return dest;
}

char *itoa_simple(char *dest, int i) {
  char *s = dest;
  if (i < 0) {
    *s++ = '-';
  } else {
    i = -i;
  }
  *itoa_simple_helper(s, i) = '\0';
  return dest;
}

int main() {
  char s[100];
  puts(itoa_simple(s, 0));
  puts(itoa_simple(s, 1));
  puts(itoa_simple(s, -1));
  puts(itoa_simple(s, 12345));
  puts(itoa_simple(s, INT_MAX-1));
  puts(itoa_simple(s, INT_MAX));
  puts(itoa_simple(s, INT_MIN+1));
  puts(itoa_simple(s, INT_MIN));
}

Salida de muestra

0
1
-1
12345
2147483646
2147483647
-2147483647
-2147483648

  • Funciona solo para constantes, no para variables.

    – Desnudo

    3 de febrero de 2014 a las 22:06

  • ¿Por qué no funciona si pongo una macro ahí…? ¿No es una constante también?

    – Edu590

    5 de febrero de 2022 a las 15:39

Avatar de usuario de Peter Mortensen
Pedro Mortensen

Si está usando GCC, puede usar la extensión GNU asprintf función.

char* str;
asprintf(&str, "%i", 12313);
free(str);

  • una justificación tal vez: “La función sprintf puede ser peligrosa porque potencialmente puede generar más caracteres de los que caben en el tamaño de asignación de la cadena s… Para evitar este problema, puede usar snprintf o asprintf

    -Peter Mortensen

    6 de febrero a las 16:43


¿Ha sido útil esta solución?