Comment convertir un int(entier) en chaîne? J'essaie de créer une fonction qui convertit les données d'un structen une chaîne pour l'enregistrer dans un fichier.
vous pouvez également consulter cette FAQ sur la sérialisation, et peut-être les questions suivantes relatives à la sérialisation en C: (a) , (b) , (c) pour atteindre votre intention réelle.
moooeeeep
2
Ma bête sémantique habituelle pour animaux de compagnie ici. Vous ne voulez rien convertir; vous souhaitez obtenir une chaîne contenant une représentation (base 10?) de la valeur de int. Ouais je sais. C'est un raccourci très courant, mais ça me dérange toujours.
EDIT: Comme indiqué dans le commentaire, ce itoa()n'est pas une norme, il vaut donc mieux utiliser l'approche sprintf () suggérée dans la réponse concurrente!
Vous pouvez utiliser la itoa()fonction pour convertir votre valeur entière en chaîne.
Voici un exemple:
int num =321;char snum[5];// convert 123 to string [buf]
itoa(num, snum,10);// print our string
printf("%s\n", snum);
Si vous souhaitez sortir votre structure dans un fichier, il n'est pas nécessaire de convertir une valeur au préalable. Vous pouvez simplement utiliser la spécification du format printf pour indiquer comment sortir vos valeurs et utiliser l'un des opérateurs de la famille printf pour sortir vos données.
Pour être sûrs que cela ENOUGHsuffit, nous pouvons le faire parmalloc(sizeof(char)*(int)log10(num))
Hauleth
2
@Hauleth Ou même +2, étant donné que (int)log10(42)c'est le cas 1.
Christian Rau
23
Ou vous pouvez le calculer au moment de la compilation:#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
caf
4
@hauleth Toujours +2 au lieu de +1, même avec ceil: ceil (log (100)) = 2.0, pas 3. Donc +1 pour les puissances exactes de 10, et encore +1 pour terminer null.
not-just-yeti
24
Vous ne considérez pas le signe moins et les paramètres régionaux: séparateur et regroupement de milliers. Veuillez le faire de cette façon: utilisez int length = snprintf(NULL, 0,"%d",42);pour obtenir la longueur, puis allouez les length+1caractères pour la chaîne.
user2622016
70
La réponse courte est:
snprintf( str, size,"%d", x );
Le plus long est: vous devez d'abord trouver une taille suffisante. snprintfvous indique la longueur si vous l'appelez avec NULL, 0comme premiers paramètres:
snprintf( NULL,0,"%d", x );
Attribuez un caractère de plus pour null-terminator.
#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 fonctionne pour chaque chaîne de format, vous pouvez donc convertir float ou double en chaîne en utilisant "%g", vous pouvez convertir int en hex en utilisant "%x", et ainsi de suite.
@ user1821961 Merci, il faut vraiment mentionner que ces fichiers d'en-tête doivent être inclus.
byxor
J'adore celui-ci, étant le plus robuste et le plus "à la mode".
Motti Shneor
30
Après avoir examiné différentes versions d'itoa pour gcc, la version la plus flexible que j'ai trouvée qui est capable de gérer les conversions en binaire, décimal et hexadécimal, à la fois positive et négative est la quatrième version trouvée sur http://www.strudel.org .uk / itoa / . Bien que sprintf/ snprintfaient des avantages, ils ne traiteront pas les nombres négatifs pour autre chose que la conversion décimale. Étant donné que le lien ci-dessus est hors ligne ou n'est plus actif, j'ai inclus leur 4ème version ci-dessous:
/**
* 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;}
En outre, cela est considérablement plus rapide que sprintf. Pourrait être important lors du dumping de gros fichiers.
Eugene Ryabtsev
@Eugene Ryabtsev C ne spécifie pas la note de performance de sprintf()et "c'est beaucoup plus rapide que sprintf" peut être vrai sur votre compilateur mais pas toujours tenir. Un compilateur peut l'examiner sprintf(str, "%d", 42);et l'optimiser pour une itoa()fonction similaire optimisée - certainement plus rapide que cet utilisateur. code.
chux
3
@chux Oui, un compilateur pourrait optimiser sprintf(str, "%d", 42);en ajoutant deux caractères const, mais c'est de la théorie. Dans la pratique, les gens ne sprintent pas et l'itoa ci-dessus est presque aussi optimisé que possible. Au moins, vous pourriez être sûr à 100% que vous n'obtiendrez pas des ordres de grandeur de déclassement d'un sprintf générique. Ce serait bien de voir le contre-exemple que vous avez en tête, avec la version et les paramètres du compilateur.
Eugene Ryabtsev
1
@chux Si cela se termine par un appel, cela n'explique pas grand-chose à moins que nous comparions la routine appelée à la routine ci-dessus (tout le long jusqu'à plus d'appels; en assembleur, si vous le souhaitez). Si vous le faites en tant que réponse avec la version et les paramètres du compilateur, je le jugerai utile.
Eugene Ryabtsev
2
Il serait bon de fournir un moyen de récupérer la longueur de sortie. Je l'ai fait ici: stackoverflow.com/a/52111436/895245 + tests unitaires.
La conversion de n'importe quoi en chaîne doit soit 1) allouer la chaîne résultante, soit 2) transmettre une char *destination et une taille. Exemple de code ci-dessous:
Les deux fonctionnent pour tous, inty compris INT_MIN. Ils fournissent une sortie cohérente contrairement à snprintf()ce qui dépend des paramètres régionaux actuels.
Méthode 1: retour NULLsur mémoire insuffisante.
#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éthode 2: elle retourne NULLsi le tampon était trop petit.
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;}
[Modifier] tel que demandé par @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3est au moins le nombre maximum de charnécessaire pour coder le type d'entier signé sous la forme d'une chaîne composée d'un signe négatif facultatif, de chiffres et d'un caractère nul.
Le nombre de bits non signés dans un entier signé n'est pas supérieur à CHAR_BIT*sizeof(int_type)-1. Une représentation en base 10 d'un nnombre binaire de bits prend jusqu'à n*log10(2) + 1chiffres. 10/33est un peu plus que log10(2). +1 pour le signe charet +1 pour le caractère nul. D'autres fractions pourraient être utilisées comme 28/93.
Méthode 3: Si l'on veut vivre sur le bord et que le débordement de tampon n'est pas un problème, une simple solution C99 ou ultérieure suit qui gère toutint .
@CiroSantilli 新疆 改造 中心 六四 事件 法轮功 Je ne connais pas l'implémentation interne de la glibc.
chux
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 vous souhaitez sortir votre structure dans un fichier, il n'est pas nécessaire de convertir une valeur au préalable. Vous pouvez simplement utiliser la spécification du format printf pour indiquer comment sortir vos valeurs et utiliser l'un des opérateurs de la famille printf pour sortir vos données.
printf
ou l'un de ses cousins devrait faire l'affaireint
. Ouais je sais. C'est un raccourci très courant, mais ça me dérange toujours.Réponses:
EDIT: Comme indiqué dans le commentaire, ce
itoa()
n'est pas une norme, il vaut donc mieux utiliser l'approche sprintf () suggérée dans la réponse concurrente!Vous pouvez utiliser la
itoa()
fonction pour convertir votre valeur entière en chaîne.Voici un exemple:
Si vous souhaitez sortir votre structure dans un fichier, il n'est pas nécessaire de convertir une valeur au préalable. Vous pouvez simplement utiliser la spécification du format printf pour indiquer comment sortir vos valeurs et utiliser l'un des opérateurs de la famille printf pour sortir vos données.
la source
itoa
n'est pas standard - voir par exemple stackoverflow.com/questions/190229/…itoa()
souffre du même potentiel de débordement de tampon quegets()
.Vous pouvez utiliser
sprintf
pour le faire, ou peutsnprintf
- être si vous l'avez:Où le nombre de caractères (plus le caractère de fin) dans le
str
peut être calculé en utilisant:la source
ENOUGH
suffit, nous pouvons le faire parmalloc(sizeof(char)*(int)log10(num))
(int)log10(42)
c'est le cas1
.#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
int length = snprintf(NULL, 0,"%d",42);
pour obtenir la longueur, puis allouez leslength+1
caractères pour la chaîne.La réponse courte est:
Le plus long est: vous devez d'abord trouver une taille suffisante.
snprintf
vous indique la longueur si vous l'appelez avecNULL, 0
comme premiers paramètres:Attribuez un caractère de plus pour null-terminator.
Si fonctionne pour chaque chaîne de format, vous pouvez donc convertir float ou double en chaîne en utilisant
"%g"
, vous pouvez convertir int en hex en utilisant"%x"
, et ainsi de suite.la source
Après avoir examiné différentes versions d'itoa pour gcc, la version la plus flexible que j'ai trouvée qui est capable de gérer les conversions en binaire, décimal et hexadécimal, à la fois positive et négative est la quatrième version trouvée sur http://www.strudel.org .uk / itoa / . Bien que
sprintf
/snprintf
aient des avantages, ils ne traiteront pas les nombres négatifs pour autre chose que la conversion décimale. Étant donné que le lien ci-dessus est hors ligne ou n'est plus actif, j'ai inclus leur 4ème version ci-dessous:la source
sprintf()
et "c'est beaucoup plus rapide que sprintf" peut être vrai sur votre compilateur mais pas toujours tenir. Un compilateur peut l'examinersprintf(str, "%d", 42);
et l'optimiser pour uneitoa()
fonction similaire optimisée - certainement plus rapide que cet utilisateur. code.sprintf(str, "%d", 42);
en ajoutant deux caractères const, mais c'est de la théorie. Dans la pratique, les gens ne sprintent pas et l'itoa ci-dessus est presque aussi optimisé que possible. Au moins, vous pourriez être sûr à 100% que vous n'obtiendrez pas des ordres de grandeur de déclassement d'un sprintf générique. Ce serait bien de voir le contre-exemple que vous avez en tête, avec la version et les paramètres du compilateur.C'est vieux mais voici une autre façon.
la source
Si vous utilisez GCC, vous pouvez utiliser la fonction d'extension GNU asprintf.
la source
La conversion de n'importe quoi en chaîne doit soit 1) allouer la chaîne résultante, soit 2) transmettre une
char *
destination et une taille. Exemple de code ci-dessous:Les deux fonctionnent pour tous,
int
y comprisINT_MIN
. Ils fournissent une sortie cohérente contrairement àsnprintf()
ce qui dépend des paramètres régionaux actuels.Méthode 1: retour
NULL
sur mémoire insuffisante.Méthode 2: elle retourne
NULL
si le tampon était trop petit.[Modifier] tel que demandé par @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3
est au moins le nombre maximum dechar
nécessaire pour coder le type d'entier signé sous la forme d'une chaîne composée d'un signe négatif facultatif, de chiffres et d'un caractère nul.Le nombre de bits non signés dans un entier signé n'est pas supérieur à
CHAR_BIT*sizeof(int_type)-1
. Une représentation en base 10 d'unn
nombre binaire de bits prend jusqu'àn*log10(2) + 1
chiffres.10/33
est un peu plus quelog10(2)
. +1 pour le signechar
et +1 pour le caractère nul. D'autres fractions pourraient être utilisées comme 28/93.Méthode 3: Si l'on veut vivre sur le bord et que le débordement de tampon n'est pas un problème, une simple solution C99 ou ultérieure suit qui gère tout
int
.Exemple de sortie
la source
la source
Si vous souhaitez sortir votre structure dans un fichier, il n'est pas nécessaire de convertir une valeur au préalable. Vous pouvez simplement utiliser la spécification du format printf pour indiquer comment sortir vos valeurs et utiliser l'un des opérateurs de la famille printf pour sortir vos données.
la source
Utilisez la fonction
itoa()
pour convertir un entier en chaînePar exemple:
la source