¿Cómo convertir un int a cadena en C?

8 minutos de lectura

avatar de usuario
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

  • posible duplicado de Convertir int a cadena en c

    – nawfal

    17 de julio de 2014 a las 7:18

avatar de usuario
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
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"y así.

  • #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
Alejandro Galkin

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


Puedes usar 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

  • @PaulR ¡Ahora no sabía eso! Gracias por la aclaración.

    – Christian Raú

    24 de noviembre de 2011 a las 13:31

  • @PaulR ¡Gracias, no sabía eso!

    – Alejandro Galkin

    24 de noviembre de 2011 a las 13:32

  • @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

avatar de usuario
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
baz

correr está devolviendo los bytes y agrega un byte nulo también:

# include <stdio.h>
# include <string.h>
int main() {
    char buf[ 1024];
    int n = sprintf( buf, "%d", 2415);
    printf( "%s %d\n", buf, n);
}

producción:

2415 4

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 todos 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

avatar de usuario
algo

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

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

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad