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) ?

118
demandé sur David Guyon 2008-10-10 09:29:51

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!

82
répondu Matt J 2010-01-07 23:36:43

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); }
12
répondu James Antill 2008-10-10 19:19:46

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

7
répondu Mark Ransom 2012-11-16 03:30:24

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 .

6
répondu Mark 2014-09-24 13:55:38

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;
     }
}  
6
répondu haccks 2016-04-03 21:15:33

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))

3
répondu mmdemirbas 2015-12-20 21:50:13

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;
}
2
répondu Chris Desjardins 2013-04-16 16:49:09

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;
}
2
répondu rick-rick-rick 2017-11-27 12:10:13

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.

1
répondu the sudhakar 2013-01-19 03:54:51

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;
}
1
répondu waaagh 2013-04-19 01:13:57

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");
} 
1
répondu Andres Romero 2014-01-16 17:40:33

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;
}
1
répondu Vlatko Šurlan 2016-04-04 12:02:30

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);
1
répondu chux 2018-05-09 18:46:22

j'ai utilisé _itoa(...) sur le compilateur RedHat 6 et GCC. Elle fonctionne.

0
répondu m_pGladiator 2008-10-10 15:46:42

glibc la mise en œuvre interne

glibc 2.28 a une implémentation interne:

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

0

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);
}
-4
répondu Archana Chatterjee 2012-09-30 01:35:08