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.
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 pormalloc(sizeof(char)*(int)log10(num))
– Hauleth
24 de noviembre de 2011 a las 13:25
-
@Hauleth O incluso +2, considerando que
(int)log10(42)
es1
.– 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 asignarlength+1
caracteres para la cadena.– usuario2622016
28 de septiembre de 2015 a las 6:10
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 quegets()
.– 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
oitoa
? ¿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
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
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;
}
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
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
oasprintf
“-Peter Mortensen
6 de febrero a las 16:43
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 quesnprintf
es más portátil.– SS Ana
24 de enero de 2020 a las 22:43