sprintf - itoa en c
Cómo convertir un int a una cadena en C (9)
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 binarias, decimales y hexadecimales, tanto positivas como negativas es la cuarta versión que se encuentra en http://www.strudel.org.uk/itoa/ . Si bien sprintf
/ snprintf
tienen ventajas, no manejarán números negativos para nada más que la conversión decimal. Como el enlace de arriba está fuera de línea o ya no está activo, he incluido su cuarta versión a continuación:
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;
}
¿Cómo se convierte un int
(integer) a una cadena? Intento crear una función que convierta los datos de una struct
en una cadena para guardarla en un archivo.
Esto es viejo, pero aquí hay otra manera.
#include <stdio.h>
#define atoa(x) #x
int main(int argc, char *argv[])
{
char *string = atoa(1234567890);
printf("%s/n", string);
return 0;
}
La conversión de cualquier cosa a una cadena debe 1) asignar la cadena resultante o 2) pasar en un destino y tamaño de char *
. Código de muestra a continuación:
Ambos funcionan para todo int
incluyendo INT_MIN
. Proporcionan un resultado consistente a diferencia de snprintf()
que depende de la configuración regional actual.
Método 1: devuelve 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: devuelve NULL
si el buffer fue 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;
}
[Editar] como solicitud de @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3
es al menos el número máximo de caracteres necesarios para codificar el 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 que no son firmas en un entero con signo no es más que CHAR_BIT*sizeof(int_type)-1
. Una representación de base 10 de un número binario n
bit toma hasta n*log10(2) + 1
dígito. 10/33
es un poco más que log10(2)
. +1 para el signo char
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 simple solución C99 o posterior que maneja todos los 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));
}
Muestra de salida
0
1
-1
12345
2147483646
2147483647
-2147483647
-2147483648
La respuesta corta es:
snprintf( str, size, "%d", x );
El más largo es: primero debe averiguar el tamaño suficiente. snprintf
te dice 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.
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, para que pueda convertir float o double en string utilizando "%g"
, puede convertir int a hex usando "%x"
, y así sucesivamente.
Puedes usar sprintf
para hacerlo, o quizás 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 str
se puede calcular usando:
(int)((ceil(log10(num))+1)*sizeof(char))
Si desea generar su estructura en un archivo, no es necesario convertir ningún valor de antemano. Puede usar la especificación de formato printf para indicar cómo dar salida a sus valores y usar cualquiera de los operadores de la familia printf para generar sus datos.
Si está utilizando GCC, puede usar la extensión GNU como función printf.
char* str;
asprintf (&str, "%i", 12313);
free(str);
EDITAR: Como se señaló en el comentario, itoa()
no es un estándar, por lo que es mejor usar el enfoque sprintf () sugerido en la respuesta rival.
Puede usar la función itoa()
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 de formato printf para indicar cómo dar salida a sus valores y usar cualquiera de los operadores de la familia printf para generar sus datos.
/*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)
return 0;
if(value==0)
{
*ptr=''0'';
return 1;
}
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;
}