Où est la fonction itoa dans Linux?
itoa()
est vraiment une fonction très pratique pour convertir un nombre en chaîne. Linux ne semble pas avoir itoa()
, est-il une fonction équivalente ou dois-je utiliser sprintf(str, "%d", num)
?
16 réponses
EDIT: Désolé, j'aurais dû rappeler que cette machine est résolument non-standard, avoir branché dans diverses organisations non-standard libc
des implémentations pour des fins académiques ;-)
comme itoa()
est en effet non standard, comme mentionné par plusieurs commentateurs utiles, il est préférable d'utiliser sprintf(target_string,"%d",source_int)
ou (mieux encore, parce qu'il est sûr des débordements de tampon) snprintf(target_string, size_of_target_string_in_bytes, "%d", source_int)
. Je sais que ce n'est pas aussi concis ou cool que itoa()
, mais au moins tu peux écrire Une fois, Exécuter Partout (tm) ;-)
Voici le vieux (édité) réponse
vous avez raison de dire que la valeur par défaut gcc libc
n'inclut pas itoa()
, comme plusieurs autres plates-formes, parce qu'elle ne fait pas techniquement partie de la norme. Voir ici pour un peu plus d'infos. Notez que vous devez
#include <stdlib.h>
bien sûr, vous le savez déjà, parce que vous vouliez utiliser itoa()
sur Linux après l'avoir probablement utilisé sur une autre plate-forme, mais... le code (volé dans le lien ci-dessus) ressemblerait à:
exemple
/* itoa example */
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int i;
char buffer [33];
printf ("Enter a number: ");
scanf ("%d",&i);
itoa (i,buffer,10);
printf ("decimal: %s\n",buffer);
itoa (i,buffer,16);
printf ("hexadecimal: %s\n",buffer);
itoa (i,buffer,2);
printf ("binary: %s\n",buffer);
return 0;
}
sortie:
Enter a number: 1750 decimal: 1750 hexadecimal: 6d6 binary: 11011010110
Espérons que cette aide!
si vous l'appelez beaucoup, le Conseil de" Il suffit d'utiliser snprintf " peut être ennuyeux. Donc voici ce que vous voulez probablement:
const char *my_itoa_buf(char *buf, size_t len, int num)
{
static char loc_buf[sizeof(int) * CHAR_BITS]; /* not thread safe */
if (!buf)
{
buf = loc_buf;
len = sizeof(loc_buf);
}
if (snprintf(buf, len, "%d", num) == -1)
return ""; /* or whatever */
return buf;
}
const char *my_itoa(int num)
{ return my_itoa_buf(NULL, 0, num); }
Edit: je viens de découvrir sur std::to_string
qui est identique à l'opération de ma propre fonction ci-dessous. Il a été introduit en C++11 et est disponible dans les versions récentes de gcc, au moins aussi tôt que 4.5 si vous activez les extensions C++0x.
Non seulement
itoa
est absent de gcc, ce n'est pas la fonction la plus difficile à utiliser puisque vous devez lui donner un tampon. J'ai besoin de quelque chose qui pourrait être utilisé dans une expression Donc j'ai inventé ceci:
std::string itos(int n)
{
const int max_size = std::numeric_limits<int>::digits10 + 1 /*sign*/ + 1 /*0-terminator*/;
char buffer[max_size] = {0};
sprintf(buffer, "%d", n);
return std::string(buffer);
}
normalement, il serait plus sûr d'utiliser snprintf
au lieu de sprintf
, mais le tampon est soigneusement dimensionné pour être à l'abri du dépassement.
voir un exemple: http://ideone.com/mKmZVE
comme L'a écrit Matt J, il y a itoa
, mais ce n'est pas standard. Votre code sera plus portable si vous utilisez snprintf
.
itoa
n'est pas une fonction C standard. Vous pouvez implémenter votre propre. Il est apparu dans la première édition de Kernighan et Ritchie's le langage de programmation C , à la page 60. La deuxième édition du langage de programmation C ("K&R2") contient la mise en œuvre suivante de itoa
, à la page 64. Le livre Note plusieurs problèmes avec cette mise en œuvre, y compris le fait que il ne traite pas correctement le nombre le plus négatif
/* itoa: convert n to characters in s */
void itoa(int n, char s[])
{
int i, sign;
if ((sign = n) < 0) /* record sign */
n = -n; /* make n positive */
i = 0;
do { /* generate digits in reverse order */
s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */
if (sign < 0)
s[i++] = '-';
s[i] = '"151900920"';
reverse(s);
}
La fonction reverse
utilisée ci-dessus est mis en œuvre deux pages plus tôt:
#include <string.h>
/* reverse: reverse string s in place */
void reverse(char s[])
{
int i, j;
char c;
for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
la fonction suivante alloue juste assez de mémoire pour garder la représentation de chaîne du nombre donné et écrit ensuite la représentation de chaîne dans cette zone en utilisant la méthode standard sprintf
.
char *itoa(long n)
{
int len = n==0 ? 1 : floor(log10l(labs(n)))+1;
if (n<0) len++; // room for negative sign '-'
char *buf = calloc(sizeof(char), len+1); // +1 for null
snprintf(buf, len+1, "%ld", n);
return buf;
}
Ne pas oublier free
jusqu'mémoire allouée lorsque de besoin:
char *num_str = itoa(123456789L);
// ...
free(num_str);
N.B. comme snprintf copie n-1 bytes, nous devons appeler snprintf (buf, len+1, "%ld", n) (pas seulement snprintf (buf, len, "%ld", n))
Voici une version améliorée de la solution D'Archana. Il fonctionne pour n'importe quel radix 1-16, et les nombres <= 0, et il ne devrait pas Clabber la mémoire.
static char _numberSystem[] = "0123456789ABCDEF";
static char _twosComp[] = "FEDCBA9876543210";
static void safestrrev(char *buffer, const int bufferSize, const int strlen)
{
int len = strlen;
if (len > bufferSize)
{
len = bufferSize;
}
for (int index = 0; index < (len / 2); index++)
{
char ch = buffer[index];
buffer[index] = buffer[len - index - 1];
buffer[len - index - 1] = ch;
}
}
static int negateBuffer(char *buffer, const int bufferSize, const int strlen, const int radix)
{
int len = strlen;
if (len > bufferSize)
{
len = bufferSize;
}
if (radix == 10)
{
if (len < (bufferSize - 1))
{
buffer[len++] = '-';
buffer[len] = '"151900920"';
}
}
else
{
int twosCompIndex = 0;
for (int index = 0; index < len; index++)
{
if ((buffer[index] >= '0') && (buffer[index] <= '9'))
{
twosCompIndex = buffer[index] - '0';
}
else if ((buffer[index] >= 'A') && (buffer[index] <= 'F'))
{
twosCompIndex = buffer[index] - 'A' + 10;
}
else if ((buffer[index] >= 'a') && (buffer[index] <= 'f'))
{
twosCompIndex = buffer[index] - 'a' + 10;
}
twosCompIndex += (16 - radix);
buffer[index] = _twosComp[twosCompIndex];
}
if (len < (bufferSize - 1))
{
buffer[len++] = _numberSystem[radix - 1];
buffer[len] = 0;
}
}
return len;
}
static int twosNegation(const int x, const int radix)
{
int n = x;
if (x < 0)
{
if (radix == 10)
{
n = -x;
}
else
{
n = ~x;
}
}
return n;
}
static char *safeitoa(const int x, char *buffer, const int bufferSize, const int radix)
{
int strlen = 0;
int n = twosNegation(x, radix);
int nuberSystemIndex = 0;
if (radix <= 16)
{
do
{
if (strlen < (bufferSize - 1))
{
nuberSystemIndex = (n % radix);
buffer[strlen++] = _numberSystem[nuberSystemIndex];
buffer[strlen] = '"151900920"';
n = n / radix;
}
else
{
break;
}
} while (n != 0);
if (x < 0)
{
strlen = negateBuffer(buffer, bufferSize, strlen, radix);
}
safestrrev(buffer, bufferSize, strlen);
return buffer;
}
return NULL;
}
Où est la fonction itoa dans Linux?
il n'y a pas de telle fonction dans Linux. J'ai utiliser ce code à la place.
/*
=============
itoa
Convert integer to string
PARAMS:
- value A 64-bit number to convert
- str Destination buffer; should be 66 characters long for radix2, 24 - radix8, 22 - radix10, 18 - radix16.
- radix Radix must be in range -36 .. 36. Negative values used for signed numbers.
=============
*/
char* itoa (unsigned long long value, char str[], int radix)
{
char buf [66];
char* dest = buf + sizeof(buf);
boolean sign = false;
if (value == 0) {
memcpy (str, "0", 2);
return str;
}
if (radix < 0) {
radix = -radix;
if ( (long long) value < 0) {
value = -value;
sign = true;
}
}
*--dest = '"151900920"';
switch (radix)
{
case 16:
while (value) {
* --dest = '0' + (value & 0xF);
if (*dest > '9') *dest += 'A' - '9' - 1;
value >>= 4;
}
break;
case 10:
while (value) {
*--dest = '0' + (value % 10);
value /= 10;
}
break;
case 8:
while (value) {
*--dest = '0' + (value & 7);
value >>= 3;
}
break;
case 2:
while (value) {
*--dest = '0' + (value & 1);
value >>= 1;
}
break;
default: // The slow version, but universal
while (value) {
*--dest = '0' + (value % radix);
if (*dest > '9') *dest += 'A' - '9' - 1;
value /= radix;
}
break;
}
if (sign) *--dest = '-';
memcpy (str, dest, buf +sizeof(buf) - dest);
return str;
}
copie directe au tampon: 64 bits entier itoa hex:
char* itoah(long num, char* s, int len)
{
long n, m = 16;
int i = 16+2;
int shift = 'a'- ('9'+1);
if(!s || len < 1)
return 0;
n = num < 0 ? -1 : 1;
n = n * num;
len = len > i ? i : len;
i = len < i ? len : i;
s[i-1] = 0;
i--;
if(!num)
{
if(len < 2)
return &s[i];
s[i-1]='0';
return &s[i-1];
}
while(i && n)
{
s[i-1] = n % m + '0';
if (s[i-1] > '9')
s[i-1] += shift ;
n = n/m;
i--;
}
if(num < 0)
{
if(i)
{
s[i-1] = '-';
i--;
}
}
return &s[i];
}
note: change long en long long long pour une machine 32 bits. long à int dans le cas de 32 bits entier. m est la base. En diminuant radix, augmentez le nombre de caractères (variable i). En augmentant radix, diminuez le nombre de caractères (mieux). Dans le cas d'un type de données non signé, je viens de devenir 16 + 1.
j'ai essayé de mon propre mise en œuvre de itoa(), il semble de travail en binaire, octal, décimal et hexadécimal
#define INT_LEN (10)
#define HEX_LEN (8)
#define BIN_LEN (32)
#define OCT_LEN (11)
static char * my_itoa ( int value, char * str, int base )
{
int i,n =2,tmp;
char buf[BIN_LEN+1];
switch(base)
{
case 16:
for(i = 0;i<HEX_LEN;++i)
{
if(value/base>0)
{
n++;
}
}
snprintf(str, n, "%x" ,value);
break;
case 10:
for(i = 0;i<INT_LEN;++i)
{
if(value/base>0)
{
n++;
}
}
snprintf(str, n, "%d" ,value);
break;
case 8:
for(i = 0;i<OCT_LEN;++i)
{
if(value/base>0)
{
n++;
}
}
snprintf(str, n, "%o" ,value);
break;
case 2:
for(i = 0,tmp = value;i<BIN_LEN;++i)
{
if(tmp/base>0)
{
n++;
}
tmp/=base;
}
for(i = 1 ,tmp = value; i<n;++i)
{
if(tmp%2 != 0)
{
buf[n-i-1] ='1';
}
else
{
buf[n-i-1] ='0';
}
tmp/=base;
}
buf[n-1] = '"151900920"';
strcpy(str,buf);
break;
default:
return NULL;
}
return str;
}
si vous voulez juste les imprimer:
void binary(unsigned int n)
{
for(int shift=sizeof(int)*8-1;shift>=0;shift--)
{
if (n >> shift & 1)
printf("1");
else
printf("0");
}
printf("\n");
}
lire le code des gars qui le font pour gagner leur vie vous fera faire un long chemin.
regardez comment les gars de MySQL l'ont fait. La source est très bien commentée et vous enseignera beaucoup plus que les solutions hackées trouvées partout.
MySQL mise en œuvre de int2str
j'ai la mentionné mise en œuvre ici; le lien est ici à titre de référence et doit être utilisé pour lire l'intégralité de l' application.
char *
int2str(long int val, char *dst, int radix,
int upcase)
{
char buffer[65];
char *p;
long int new_val;
char *dig_vec= upcase ? _dig_vec_upper : _dig_vec_lower;
ulong uval= (ulong) val;
if (radix < 0)
{
if (radix < -36 || radix > -2)
return NullS;
if (val < 0)
{
*dst++ = '-';
/* Avoid integer overflow in (-val) for LLONG_MIN (BUG#31799). */
uval = (ulong)0 - uval;
}
radix = -radix;
}
else if (radix > 36 || radix < 2)
return NullS;
/*
The slightly contorted code which follows is due to the fact that
few machines directly support unsigned long / and %. Certainly
the VAX C compiler generates a subroutine call. In the interests
of efficiency (hollow laugh) I let this happen for the first digit
only; after that "val" will be in range so that signed integer
division will do. Sorry 'bout that. CHECK THE CODE PRODUCED BY
YOUR C COMPILER. The first % and / should be unsigned, the second
% and / signed, but C compilers tend to be extraordinarily
sensitive to minor details of style. This works on a VAX, that's
all I claim for it.
*/
p = &buffer[sizeof(buffer)-1];
*p = '"151900920"';
new_val= uval / (ulong) radix;
*--p = dig_vec[(uchar) (uval- (ulong) new_val*(ulong) radix)];
val = new_val;
while (val != 0)
{
ldiv_t res;
res=ldiv(val,radix);
*--p = dig_vec[res.rem];
val= res.quot;
}
while ((*dst++ = *p++) != 0) ;
return dst-1;
}
Où est la fonction itoa dans Linux?
comme itoa()
n'est pas standard en C, différentes versions avec différentes signatures de fonction existent.
char *itoa(int value, char *str, int base);
est commun dans *nix.
S'il est absent de Linux ou si le code ne veut pas limiter la portabilité, le code pourrait le rendre propre.
ci-dessous est une version qui n'a pas de problème avec INT_MIN
et gère les tampons de problèmes: NULL
ou un tampon insuffisant renvoie NULL
.
#include <stdlib.h>
#include <limits.h>
#include <string.h>
// Buffer sized for a decimal string of a `signed int`, 28/93 > log10(2)
#define SIGNED_PRINT_SIZE(object) ((sizeof(object) * CHAR_BIT - 1)* 28 / 93 + 3)
char *itoa_x(int number, char *dest, size_t dest_size) {
if (dest == NULL) {
return NULL;
}
char buf[SIGNED_PRINT_SIZE(number)];
char *p = &buf[sizeof buf - 1];
// Work with negative absolute value
int neg_num = number < 0 ? number : -number;
// Form string
*p = '"151900920"';
do {
*--p = (char) ('0' - neg_num % 10);
neg_num /= 10;
} while (neg_num);
if (number < 0) {
*--p = '-';
}
// Copy string
size_t src_size = (size_t) (&buf[sizeof buf] - p);
if (src_size > dest_size) {
// Not enough room
return NULL;
}
return memcpy(dest, p, src_size);
}
ci-dessous est une version C99 ou ultérieure qui traite toute base [2...36]
char *itoa_x(int number, char *dest, size_t dest_size, int base) {
if (dest == NULL || base < 2 || base > 36) {
return NULL;
}
char buf[sizeof number * CHAR_BIT + 2]; // worst case: itoa(INT_MIN,,,2)
char *p = &buf[sizeof buf - 1];
// Work with negative absolute value to avoid UB of `abs(INT_MIN)`
int neg_num = number < 0 ? number : -number;
// Form string
*p = '"151910920"';
do {
*--p = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[-(neg_num % base)];
neg_num /= base;
} while (neg_num);
if (number < 0) {
*--p = '-';
}
// Copy string
size_t src_size = (size_t) (&buf[sizeof buf] - p);
if (src_size > dest_size) {
// Not enough room
return NULL;
}
return memcpy(dest, p, src_size);
}
pour un code conforme à la norme C89 et ultérieure, remplacer "inner loop" par
." div_t qr;
do {
qr = div(neg_num, base);
*--p = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[-qr.rem];
neg_num = qr.quot;
} while (neg_num);
j'ai utilisé _itoa(...) sur le compilateur RedHat 6 et GCC. Elle fonctionne.
glibc la mise en œuvre interne
glibc 2.28 a une implémentation interne:
- https://sourceware.org/git/?p=glibc.git;a=blob;f=stdio-common/_itoa.c;h=3749ee97e320ceb62cbf76b6c93dd2beb38fe157;hb=3c03baca37fdcb52c3881e653ca392bba7a99c2b 1519100920"
- https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/generic/_itoa.h;h=3749ee97e320ceb62cbf76b6c93dd2beb38fe157;hb=3c03baca37fdcb52c3881e653ca392bba7a99c2b 1519100920"
qui est utilisé à plusieurs endroits à l'intérieur, mais je n'ai pas pu trouver si elle peut être exposée ou comment.
Au moins, cela devrait être une mise en œuvre robuste si vous êtes prêt pour l'extraire.
cette question demande comment rouler votre propre: Comment convertir Un int en chaîne de caractères en C
vous pouvez utiliser ce programme à la place de sprintf.
void itochar(int x, char *buffer, int radix);
int main()
{
char buffer[10];
itochar(725, buffer, 10);
printf ("\n %s \n", buffer);
return 0;
}
void itochar(int x, char *buffer, int radix)
{
int i = 0 , n,s;
n = s;
while (n > 0)
{
s = n%radix;
n = n/radix;
buffer[i++] = '0' + s;
}
buffer[i] = '"151900920"';
strrev(buffer);
}