Como você converte um int(inteiro) em uma string? Eu estou tentando fazer uma função que converte os dados de um structem uma seqüência de caracteres para salvá-lo em um arquivo.
você também pode querer consultar estas perguntas frequentes sobre serialização e talvez as seguintes perguntas relacionadas à serialização em C: (a) , (b) , (c) para atingir sua intenção real.
moooeeeep
2
Minha irritação semântica habitual aqui. Você não quer converter nada; você deseja obter uma string contendo uma representação (base 10?) do valor de int. Sim, eu sei. É um atalho muito comum, mas ainda me incomoda.
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.
Para ter certeza tat ENOUGHé suficiente, podemos fazê-lomalloc(sizeof(char)*(int)log10(num))
Hauleth
2
@ Hauleth Ou mesmo +2, considerando que (int)log10(42)é 1.
Christian Rau
23
Ou você pode calculá-lo em tempo de compilação:#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
caf
4
@hauleth Ainda +2 em vez de +1, mesmo com ceil: ceil (log (100)) = 2.0, não 3. Portanto, +1 para a potência exata de 10 e outra +1 para terminar nulo.
não-apenas-yeti
24
Você não considera sinal de menos e localidade: separador e agrupamento de milhares. Por favor, faça desta maneira: use int length = snprintf(NULL, 0,"%d",42);para obter comprimento e, em seguida, aloque length+1chars para a string.
user2622016
70
A resposta curta é:
snprintf( str, size,"%d", x );
Quanto mais tempo: primeiro você precisa descobrir o tamanho suficiente. snprintfinforma o comprimento se você o chamar com os NULL, 0primeiros 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.
@ user1821961 Obrigado, deve realmente ser mencionado que esses arquivos de cabeçalho precisam ser incluídos.
Bydor
Eu amo esse, por ser o mais robusto e "pelo jeito".
Motti Shneor 27/03/19
30
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/ snprintftê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 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;}
Além disso, isso é consideravelmente mais rápido que o sprintf. Pode ser importante ao descarregar arquivos grandes.
Eugene Ryabtsev
@Eugene Ryabtsev C não especifica a classificação de desempenho 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.
chux - Restabelece Monica
3
@chux Sim, um compilador pode otimizar 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.
Eugene Ryabtsev
1
@chux Se termina em uma chamada, não explica muito, a menos que comparemos a rotina chamada com a rotina acima (até não mais chamadas; em montagem, se você preferir). Se você fizer isso como uma resposta com a versão e as configurações do compilador, votarei como útil.
Eugene Ryabtsev
2
Seria bom fornecer uma maneira de recuperar o comprimento da saída. Eu fiz isso aqui: stackoverflow.com/a/52111436/895245 + testes de unidade.
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, intinclusive INT_MIN. Eles fornecem uma saída consistente, diferente da snprintf()que depende do código do idioma atual.
Método 1: Retorna NULLem 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 NULLse o buffer era muito pequeno.
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] a pedido de @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3é pelo menos o número máximo charnecessá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 nnúmero binário de bits depende de n*log10(2) + 1dígitos. 10/33é um pouco mais que log10(2). +1 para o sinal chare +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 todosint .
@CiroSantilli 法轮功 改造 中心 六四 事件 法轮功 Não estou familiarizado com a implementação interna da glibc.
chux - Restabelece 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;}
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.
printf
ou um de seus primos deve fazer o truqueint
. 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:
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.
fonte
itoa
não é padrão - veja, por exemplo, stackoverflow.com/questions/190229/…itoa()
sofre o mesmo potencial de estouro de buffer quegets()
.Você pode usar
sprintf
para fazer isso, ou talvezsnprintf
se tiver:Onde o número de caracteres (mais o caractere final) no
str
pode ser calculado usando:fonte
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, aloquelength+1
chars para a string.A resposta curta é:
Quanto mais tempo: primeiro você precisa descobrir o tamanho suficiente.
snprintf
informa o comprimento se você o chamar com osNULL, 0
primeiros parâmetros:Aloque mais um caractere para terminador nulo.
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.fonte
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:fonte
sprintf()
e "isso é consideravelmente mais rápido que o sprintf" pode ser verdade no seu compilador, mas nem sempre é válido. Um compilador pode procurarsprintf(str, "%d", 42);
e otimizar para umaitoa()
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.
fonte
Se você estiver usando o GCC, poderá usar a função de extensão GNU asprintf.
fonte
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
inclusiveINT_MIN
. Eles fornecem uma saída consistente, diferente dasnprintf()
que depende do código do idioma atual.Método 1: Retorna
NULL
em falta de memória.Método 2: Retorna
NULL
se o buffer era muito pequeno.[Editar] a pedido de @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3
é pelo menos o número máximochar
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 umn
número binário de bits depende den*log10(2) + 1
dígitos.10/33
é um pouco mais quelog10(2)
. +1 para o sinalchar
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
.Saída de amostra
fonte
fonte
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.
fonte
Use a função
itoa()
para converter um número inteiro em uma stringPor exemplo:
fonte