Como você converte um int
(inteiro) em uma string? Eu estou tentando fazer uma função que converte os dados de um struct
em uma seqüência de caracteres para salvá-lo em um arquivo.
int
. Sim, eu sei. É um atalho muito comum, mas ainda me incomoda.
Como você converte um int
(inteiro) em uma string? Eu estou tentando fazer uma função que converte os dados de um struct
em uma seqüência de caracteres para salvá-lo em um arquivo.
int
. Sim, eu sei. É um atalho muito comum, mas ainda me incomoda.
Respostas:
EDIT: Como apontado no comentário, itoa()
não é um padrão, portanto, use melhor a abordagem sprintf () sugerida na resposta rival!
Você pode usar a itoa()
função para converter seu valor inteiro em uma sequência.
Aqui está um exemplo:
int num = 321;
char snum[5];
// convert 123 to string [buf]
itoa(num, snum, 10);
// print our string
printf("%s\n", snum);
Se você deseja exibir sua estrutura em um arquivo, não há necessidade de converter nenhum valor antecipadamente. Você pode apenas usar a especificação de formato printf para indicar como imprimir seus valores e usar qualquer um dos operadores da família printf para imprimir seus dados.
itoa
não é padrão - veja, por exemplo, stackoverflow.com/questions/190229/…
itoa()
sofre o mesmo potencial de estouro de buffer que gets()
.
Você pode usar sprintf
para fazer isso, ou talvez snprintf
se tiver:
char str[ENOUGH];
sprintf(str, "%d", 42);
Onde o número de caracteres (mais o caractere final) no str
pode ser calculado usando:
(int)((ceil(log10(num))+1)*sizeof(char))
ENOUGH
é suficiente, podemos fazê-lomalloc(sizeof(char)*(int)log10(num))
(int)log10(42)
é 1
.
#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
int length = snprintf(NULL, 0,"%d",42);
para obter comprimento e, em seguida, aloque length+1
chars para a string.
A resposta curta é:
snprintf( str, size, "%d", x );
Quanto mais tempo: primeiro você precisa descobrir o tamanho suficiente. snprintf
informa o comprimento se você o chamar com os NULL, 0
primeiros parâmetros:
snprintf( NULL, 0, "%d", x );
Aloque mais um caractere para 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);
Se funcionar para todas as strings de formato, você poderá converter float ou double em string usando "%g"
, você pode converter int em hexadecimal usando "%x"
e assim por diante.
Depois de analisar várias versões do itoa para o gcc, a versão mais flexível que achei capaz de lidar com conversões em binárias, decimais e hexadecimais, positivas e negativas, é a quarta versão encontrada em http://www.strudel.org .uk / itoa / . Enquanto sprintf
/ snprintf
têm vantagens, eles não vão lidar com números negativos para outra coisa senão a conversão decimal. Como o link acima está off-line ou não está mais ativo, incluímos a quarta versão abaixo:
/**
* 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;
}
sprintf()
e "isso é consideravelmente mais rápido que o sprintf" pode ser verdade no seu compilador, mas nem sempre é válido. Um compilador pode procurar sprintf(str, "%d", 42);
e otimizar para uma itoa()
função semelhante otimizada - certamente mais rápido que esse usuário. código.
sprintf(str, "%d", 42);
como anexar dois caracteres const, mas isso é teoria. Na prática, as pessoas não correm constantemente e a itoa acima é quase tão otimizada quanto possível. Pelo menos você pode ter 100% de certeza de que não obteria ordens de magnitude inferior a um sprintf genérico. Seria bom ver qualquer contra-exemplo que você tenha em mente, com a versão e as configurações do compilador.
Isso é antigo, mas aqui está outra maneira.
#include <stdio.h>
#define atoa(x) #x
int main(int argc, char *argv[])
{
char *string = atoa(1234567890);
printf("%s\n", string);
return 0;
}
Se você estiver usando o GCC, poderá usar a função de extensão GNU asprintf.
char* str;
asprintf (&str, "%i", 12313);
free(str);
A conversão de qualquer coisa em uma sequência de caracteres deve 1) alocar a sequência resultante ou 2) passar em um char *
destino e tamanho. Código de exemplo abaixo:
Ambos funcionam para todos, int
inclusive INT_MIN
. Eles fornecem uma saída consistente, diferente da snprintf()
que depende do código do idioma atual.
Método 1: Retorna NULL
em falta de memória.
#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: Retorna NULL
se o buffer era muito pequeno.
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] a pedido de @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3
é pelo menos o número máximo char
necessário para codificar algum tipo de número inteiro assinado como uma sequência que consiste em um sinal negativo opcional, dígitos e um caractere nulo.
O número de bits não assinados em um número inteiro assinado não passa de CHAR_BIT*sizeof(int_type)-1
. Uma representação de base 10 de um n
número binário de bits depende de n*log10(2) + 1
dígitos. 10/33
é um pouco mais que log10(2)
. +1 para o sinal char
e +1 para o caractere nulo. Outras frações podem ser usadas como 28/93.
Método 3: Se alguém deseja viver no limite e o estouro de buffer não é uma preocupação, segue uma solução C99 simples ou posterior que lida com 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));
}
Saída de amostra
0
1
-1
12345
2147483646
2147483647
-2147483647
-2147483648
/*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;
}
Se você deseja exibir sua estrutura em um arquivo, não há necessidade de converter nenhum valor antecipadamente. Você pode apenas usar a especificação de formato printf para indicar como imprimir seus valores e usar qualquer um dos operadores da família printf para imprimir seus dados.
Use a função itoa()
para converter um número inteiro em uma string
Por exemplo:
char msg[30];
int num = 10;
itoa(num,msg,10);
printf
ou um de seus primos deve fazer o truque