webentwicklung-frage-antwort-db.com.de

Wo ist die Itoa-Funktion in Linux?

itoa() ist eine sehr praktische Funktion, um eine Zahl in eine Zeichenfolge umzuwandeln. Linux scheint itoa() nicht zu haben, gibt es eine gleichwertige Funktion oder muss ich sprintf(str, "%d", num) verwenden?

124
Adam Pierce

BEARBEITEN: Sorry, ich hätte daran denken müssen, dass diese Maschine eindeutig nicht standardisiert ist, da sie verschiedene nicht-standardmäßige libc-Implementierungen für akademische Zwecke eingebaut hat ;-)

Da itoa() in der Tat kein Standard ist, wie von mehreren hilfreichen Kommentatoren erwähnt, ist es am besten, sprintf(target_string,"%d",source_int) oder (besser noch, weil es vor Pufferüberläufen sicher ist) snprintf(target_string, size_of_target_string_in_bytes, "%d", source_int) zu verwenden. Ich weiß, es ist nicht ganz so prägnant oder cool wie itoa(), aber Sie können wenigstens einmal schreiben, überall laufen (tm) ;-)

Hier ist die alte (bearbeitete) Antwort

Sie geben zu Recht an, dass der Standardwert gcc libc wie mehrere andere Plattformen nicht itoa() enthält, da er technisch nicht Teil des Standards ist. Sehen Sie hier für ein paar weitere Informationen. Beachten Sie, dass Sie müssen 

#include <stdlib.h>

Natürlich wissen Sie dies bereits, weil Sie useitoa() unter Linux verwenden wollten, nachdem Sie es vermutlich auf einer anderen Plattform verwendet haben, aber ... der Code (aus dem Link oben gestohlen) würde folgendermaßen aussehen:

Beispiel

/* 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;
}

Ausgabe:

Enter a number: 1750
decimal: 1750
hexadecimal: 6d6
binary: 11011010110

Hoffe das hilft!

87
Matt J

Wenn Sie es häufig aufrufen, kann der Hinweis "einfach snprintf verwenden" ärgerlich sein. Also hier ist was Sie wahrscheinlich wollen:

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
James Antill

itoa ist keine Standard-C-Funktion. Sie können Ihre eigenen implementieren. Es erschien in der ersten Ausgabe von Kernighan und Ritchie'sDie C-Programmiersprache auf Seite 60. Die zweite Ausgabe von The C Programming Language ("K & R2") enthält die folgende Implementierung von itoa, auf Seite 64. Das Buch weist auf einige Probleme mit dieser Implementierung hin, einschließlich der Tatsache, dass die negativste Zahl nicht richtig verarbeitet. 

 /* 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] = '\0';
     reverse(s);
}  

Die oben verwendete Funktion reverse ist zwei Seiten zuvor implementiert:

 #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;
     }
}  
10
haccks

Edit: Ich habe gerade etwas über std::to_string herausgefunden, das im Betrieb mit meiner eigenen Funktion unten identisch ist. Es wurde in C++ 11 eingeführt und ist in den letzten Versionen von gcc verfügbar, mindestens jedoch mit Version 4.5, wenn Sie die C++ - 0x-Erweiterungen ..__ aktivieren.


Nicht nur itoa fehlt in gcc, es ist nicht die einfachste Funktion, die Sie verwenden müssen, da Sie ihm einen Puffer zuführen müssen. Ich brauchte etwas, das in einem Ausdruck verwendet werden konnte, also kam ich dazu:

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

Normalerweise wäre es sicherer, snprintf anstelle von sprintf zu verwenden, der Puffer ist jedoch sorgfältig so bemessen, dass er nicht überläuft.

Sehen Sie ein Beispiel: http://ideone.com/mKmZVE

7
Mark Ransom

Wie Matt J schrieb, gibt es itoa, aber das ist kein Standard. Ihr Code wird tragbarer, wenn Sie snprintf verwenden.

6
Mike

Die folgende Funktion reserviert gerade genug Speicherplatz, um die angegebene Anzahl der Zeichenketten darzustellen, und schreibt die Zeichenfolgendarstellung dann mit der sprintf-Methode in diesen Bereich.

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;
}

Vergessen Sie nicht, free den zugewiesenen Speicher zu erhöhen, wenn er nicht benötigt wird:

char *num_str = itoa(123456789L);
// ... 
free(num_str);

N.B. Da snprintf n-1 Bytes kopiert, müssen wir snprintf (buf, len + 1, "% ld", n) aufrufen (nicht nur snprintf (buf, len, "% ld", n)).

4
mmdemirbas

Wo ist die Itoa-Funktion in Linux?

In Linux gibt es keine solche Funktion. Ich benutze stattdessen diesen Code.

/*
=============
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 = '\0';

    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;
}
3
rick-rick-rick

Hier ist eine stark verbesserte Version der Archana-Lösung. Es funktioniert für jedes Radix 1-16 und für Zahlen <= 0 und sollte den Speicher nicht beeinträchtigen. 

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] = '\0';
        }
    }
    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] = '\0';
                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

Wenn Sie den Code von Leuten lesen, die es für Ihren Lebensunterhalt tun, erhalten Sie einen LANGEN WEG.

Schauen Sie sich an, wie Jungs von MySQL es geschafft haben. Die Quelle ist SEHR GUT KOMMENTIERT und lehrt Sie viel mehr als gehackte Lösungen, die überall zu finden sind.

MySQL-Implementierung von int2str

Ich führe die erwähnte Implementierung hier aus; Der Link dient hier als Referenz und sollte verwendet werden, um die vollständige Implementierung zu lesen.

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 = '\0';
  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
Vlatko Šurlan

Wenn Sie sie nur ausdrucken möchten:

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
Andres Romero

Wo ist die Itoa-Funktion in Linux?

Da itoa() kein Standard in C ist, gibt es verschiedene Versionen mit verschiedenen Funktionssignaturen.
char *itoa(int value, char *str, int base); ist in * nix üblich.

Sollte es unter Linux fehlen oder wenn der Code die Portabilität nicht einschränken möchte, kann der Code ihn eigen machen.

Nachfolgend finden Sie eine Version, die mit INT_MIN keine Probleme hat und Problempuffer behandelt: NULL oder ein nicht ausreichender Puffer gibt NULL zurück.

#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 = '\0';
  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);
}

Nachfolgend finden Sie eine C99-Version oder eine neuere Version, die für jede Basis geeignet ist [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 = '\0';
  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);
}

Ersetzen Sie bei einem C89-Code und weiterem Code die innere Schleife mit

  div_t qr;
  do {
    qr = div(neg_num, base);
    *--p = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[-qr.rem];
    neg_num = qr.quot;
  } while (neg_num);
1
chux

glibc interne Implementierung

glibc 2.28 hat eine interne Implementierung:

das wird an mehreren stellen intern verwendet, aber ich konnte nicht finden, ob es ausgesetzt werden kann oder wie.

Zumindest sollte dies eine robuste Implementierung sein, wenn Sie bereit sind, sie zu extrahieren.

In dieser Frage wird gefragt, wie Sie Ihre eigenen Werte rollen können: Wie konvertiert man einen int in einen String in C?

direktes Kopieren in den Puffer: 64-Bit-Ganzzahl-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];
    }

hinweis: Für 32-Bit-Maschine lange bis lange ändern. lang bis int für den Fall einer 32-Bit-Ganzzahl. m ist die Basis. Erhöhen Sie die Anzahl der Zeichen (Variable i), wenn Sie den Radix verringern. Verringern Sie bei Erhöhung der Radix die Anzahl der Zeichen (besser). Im Falle eines vorzeichenlosen Datentyps wird i gerade 16 + 1.

1
the sudhakar

ich habe meine eigene Implementierung von Itoa () ausprobiert, es scheint die Arbeit in binärer, oktaler, dezimaler und hexadezimaler Darstellung zu sein

#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] = '\0';
            strcpy(str,buf);
            break;
        default:
            return NULL;
    }
    return str;
}
1
waaagh

Der Austausch mit snprintf ist NICHT abgeschlossen!

Es deckt nur Basen ab: 2, 8, 10, 16, während itoa für Basen zwischen 2 und 36 funktioniert.

Da ich nach einem Ersatz für die Basis 32 gesucht habe, muss ich wohl meinen eigenen Code erstellen!

0
Zakhar

Ich würde dies vorziehen: https://github.com/wsq003/itoa_for_linux

Es sollte das schnellste itoa () sein, das es je gab. Wir verwenden aus Performancegründen itoa () anstelle von sprintf (), daher ist ein schnellstes itoa () mit eingeschränkter Funktionalität sinnvoll und lohnenswert.

0
Shaoquan

Ich habe _itoa (...) für RedHat 6 und GCC Compiler verwendet. Es klappt.

0
m_pGladiator