¿Cómo se convierte un int(entero) en una cadena? Estoy tratando de hacer una función que convierta los datos de a structen una cadena para guardarlos en un archivo.
También es posible que 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.
moooeeeep
2
Mi habitual mascota semántica molesta aquí. No quieres convertir nada; desea obtener una cadena que contenga una representación (¿base 10?) del valor de int. Si lo se. Es un atajo muy común, pero todavía me molesta.
EDITAR: Como se señaló en el comentario, itoa()no es un estándar, ¡así que mejor use el enfoque sprintf () sugerido en la respuesta rival!
Puede usar la itoa()función para convertir su valor entero en 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. Puede usar la especificación del formato printf para indicar cómo generar sus valores y utilizar cualquiera de los operadores de la familia printf para generar sus datos.
Para estar seguros de que tat ENOUGHes suficiente, podemos hacerlomalloc(sizeof(char)*(int)log10(num))
Hauleth
2
@Hauleth O incluso +2, considerando que (int)log10(42)es así 1.
Christian Rau
23
O se puede calcular en tiempo de compilación:#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
CAF
44
@hauleth Todavía +2 en lugar de +1, incluso con ceil: ceil (log (100)) = 2.0, no 3. Entonces +1 para las potencias exactas de 10, y otro +1 para terminar nulo.
not-just-yeti
24
No tiene en cuenta el signo menos y la configuración regional: separador de miles y agrupación. int length = snprintf(NULL, 0,"%d",42);Hágalo de esta manera: use para obtener longitud y luego asigne length+1caracteres para la cadena.
user2622016
70
La respuesta corta es:
snprintf( str, size,"%d", x );
Cuanto más largo sea: primero debe averiguar el tamaño suficiente. snprintfle dice longitud si lo llama con los NULL, 0primeros parámetros:
snprintf( NULL,0,"%d", x );
Asigne un carácter más para nulo-terminador.
#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, por lo que puede convertir flotante o doble a cadena usando "%g", puede convertir int a hexadecimal usando "%x", y así sucesivamente.
@ user1821961 Gracias, realmente debería mencionarse que estos archivos de encabezado deben incluirse.
byxor
Me encanta este, siendo el más robusto y "por el libro".
Motti Shneor
30
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 positiva como negativa, es la cuarta versión encontrada en http://www.strudel.org .uk / itoa / . Si bien sprintf/ snprintftienen 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 validif(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 signif(tmp_value <0)*ptr++='-';*ptr--='\0';while(ptr1 < ptr){
tmp_char =*ptr;*ptr--=*ptr1;*ptr1++= tmp_char;}return result;}
Además, esto es considerablemente más rápido que sprintf. Podría ser importante al volcar archivos grandes.
Eugene Ryabtsev
@Eugene Ryabtsev C no especifica la calificación de rendimiento de sprintf()y "esto es considerablemente más rápido que sprintf" puede ser cierto en su compilador pero no siempre se cumple. Un compilador puede analizarlo sprintf(str, "%d", 42);y optimizarlo para una itoa()función similar optimizada , ciertamente más rápido que este usuario. código.
chux
3
@chux Sí, un compilador podría optimizar sprintf(str, "%d", 42);como anexar dos caracteres constantes, pero eso es teoría. En la práctica, las personas no realizan constantes de sprint y el itoa anterior está casi tan optimizado como parece. Al menos, podría estar 100% seguro de que no obtendría órdenes de magnitud de degradación de un sprintf genérico. Sería bueno ver cualquier contraejemplo que tenga en mente, con la versión y la configuración del compilador.
Eugene Ryabtsev
1
@chux Si termina en una llamada, no explica mucho a menos que comparemos la rutina llamada con la rutina anterior (hasta llegar a no más llamadas; en conjunto, si lo desea). Si lo hace como respuesta con la versión y la configuración del compilador, lo votaré como útil.
Eugene Ryabtsev
2
Sería bueno proporcionar una forma de recuperar la longitud de salida. Lo he hecho aquí: stackoverflow.com/a/52111436/895245 + pruebas unitarias.
La conversión de cualquier cosa a una cadena debe 1) asignar la cadena resultante o 2) pasar un char *destino y un tamaño. Código de muestra a continuación:
Ambos funcionan para todos, intincluidos INT_MIN. Proporcionan una salida consistente a diferencia de lo snprintf()que depende de la configuración regional actual.
#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 NULLsi el búfer era demasiado pequeño.
staticchar*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;}
[Editar] como solicitud de @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3es al menos el número máximo charnecesario 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 más que CHAR_BIT*sizeof(int_type)-1. Una representación en base 10 de un nnúmero binario de un bit ocupa hasta n*log10(2) + 1dígitos. 10/33es un poco más que log10(2). +1 para el signo chary +1 para el carácter nulo. Otras fracciones podrían usarse 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 todoint .
@CiroSantilli 新疆 改造 中心 六四 事件 法轮功 No estoy familiarizado con la implementación interna de glibc.
chux - Restablecer Monica
3
/*Function return size of string and convert signed *
*integer to ascii value and store them in array of *
*character with NULL at the end of the array */int itoa(int value,char*ptr){int count=0,temp;if(ptr==NULL)return0;if(value==0){*ptr='0';return1;}if(value<0){
value*=(-1);*ptr++='-';
count++;}for(temp=value;temp>0;temp/=10,ptr++);*ptr='\0';for(temp=value;temp>0;temp/=10){*--ptr=temp%10+'0';
count++;}return count;}
Si desea generar su estructura en un archivo, no es necesario convertir ningún valor de antemano. Puede usar la especificación del formato printf para indicar cómo generar sus valores y utilizar cualquiera de los operadores de la familia printf para generar sus datos.
printf
o uno de sus primos debería hacer el trucoint
. Si lo se. Es un atajo muy común, pero todavía me molesta.Respuestas:
EDITAR: Como se señaló en el comentario,
itoa()
no es un estándar, ¡así que mejor use el enfoque sprintf () sugerido en la respuesta rival!Puede usar la
itoa()
función para convertir su valor entero en una cadena.Aquí hay un ejemplo:
Si desea generar su estructura en un archivo, no es necesario convertir ningún valor de antemano. Puede usar la especificación del formato printf para indicar cómo generar sus valores y utilizar cualquiera de los operadores de la familia printf para generar sus datos.
fuente
itoa
no es estándar; consulte, por ejemplo, stackoverflow.com/questions/190229/…itoa()
sufre el mismo potencial de desbordamiento de búfer quegets()
.Puedes usarlo
sprintf
para hacerlo, o tal vezsnprintf
si lo tienes:Donde
str
se puede calcular el número de caracteres (más el carácter final) en :fuente
ENOUGH
es suficiente, podemos hacerlomalloc(sizeof(char)*(int)log10(num))
(int)log10(42)
es así1
.#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
int length = snprintf(NULL, 0,"%d",42);
Hágalo de esta manera: use para obtener longitud y luego asignelength+1
caracteres para la cadena.La respuesta corta es:
Cuanto más largo sea: primero debe averiguar el tamaño suficiente.
snprintf
le dice longitud si lo llama con losNULL, 0
primeros parámetros:Asigne un carácter más para nulo-terminador.
Si funciona para cada cadena de formato, por lo que puede convertir flotante o doble a cadena usando
"%g"
, puede convertir int a hexadecimal usando"%x"
, y así sucesivamente.fuente
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 positiva como negativa, es la cuarta versión encontrada en http://www.strudel.org .uk / itoa / . Si bien
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:fuente
sprintf()
y "esto es considerablemente más rápido que sprintf" puede ser cierto en su compilador pero no siempre se cumple. Un compilador puede analizarlosprintf(str, "%d", 42);
y optimizarlo para unaitoa()
función similar optimizada , ciertamente más rápido que este usuario. código.sprintf(str, "%d", 42);
como anexar dos caracteres constantes, pero eso es teoría. En la práctica, las personas no realizan constantes de sprint y el itoa anterior está casi tan optimizado como parece. Al menos, podría estar 100% seguro de que no obtendría órdenes de magnitud de degradación de un sprintf genérico. Sería bueno ver cualquier contraejemplo que tenga en mente, con la versión y la configuración del compilador.Esto es viejo pero aquí hay otra forma.
fuente
Si está usando GCC, puede usar la extensión GNU asprintf function.
fuente
La conversión de cualquier cosa a una cadena debe 1) asignar la cadena resultante o 2) pasar un
char *
destino y un tamaño. Código de muestra a continuación:Ambos funcionan para todos,
int
incluidosINT_MIN
. Proporcionan una salida consistente a diferencia de losnprintf()
que depende de la configuración regional actual.Método 1: Devoluciones
NULL
en memoria insuficiente.Método 2: vuelve
NULL
si el búfer era demasiado pequeño.[Editar] como solicitud de @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3
es al menos el número máximochar
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 más que
CHAR_BIT*sizeof(int_type)-1
. Una representación en base 10 de unn
número binario de un bit ocupa hastan*log10(2) + 1
dígitos.10/33
es un poco más quelog10(2)
. +1 para el signochar
y +1 para el carácter nulo. Otras fracciones podrían usarse 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
.Salida de muestra
fuente
fuente
Si desea generar su estructura en un archivo, no es necesario convertir ningún valor de antemano. Puede usar la especificación del formato printf para indicar cómo generar sus valores y utilizar cualquiera de los operadores de la familia printf para generar sus datos.
fuente
Use la función
itoa()
para convertir un entero en una cadenaPor ejemplo:
fuente