IT박스

리눅스에서 itoa 기능은 어디에 있습니까?

itboxs 2020. 7. 1. 08:18
반응형

리눅스에서 itoa 기능은 어디에 있습니까?


itoa()숫자를 문자열로 변환하는 정말 편리한 함수입니다. 리눅스에는없는 것 같습니다 itoa(). 동등한 기능이 sprintf(str, "%d", num)있습니까? 아니면 사용해야 합니까?


편집 : 죄송합니다, 나는이 기계가 libc학문적 목적을 위해 다양한 비표준 구현에 연결되어 결정적으로 비표준이라는 것을 기억해야 합니다. ;-)

으로 itoa()여러 도움이 덧글에 의해 언급 한 바와 같이, 참으로 표준이 아닌, 그것을 사용하는 것이 가장 좋습니다 sprintf(target_string,"%d",source_int)(이 버퍼 오버 플로우로부터 안전하기 때문에, 더 나은 아직) 나 snprintf(target_string, size_of_target_string_in_bytes, "%d", source_int). 나는 그것이 간결하거나 시원하지 않다는 것을 알고 itoa()있지만 적어도 한 번만 쓸 수 있습니다 .Run Everywhere (tm) ;-)

여기에 오래된 (편집 된) 답변이 있습니다

기술적으로 표준의 일부가 아니기 때문에 기본값 gcc libc에는 itoa()다른 여러 플랫폼과 같이 기본값 이 포함되어 있지 않다고 말하는 것이 맞습니다 . 좀 더 자세한 정보는 여기참조 하십시오 . 당신이해야합니다

#include <stdlib.h>

물론 다른 플랫폼에서 Linux를 사용한 후 Linux 에서 사용 하기를 원했기 때문에 이미 알고 itoa()있습니다.하지만 위의 링크에서 도난당한 코드는 다음과 같습니다.

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

산출:

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

도움이 되었기를 바랍니다!


당신이 그것을 많이 부르고 있다면, "그냥 snprintf를 사용하십시오"라는 조언은 성 가실 수 있습니다. 그래서 여기 당신이 원하는 것이 있습니다 :

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

itoa표준 C 함수가 아닙니다. 당신은 당신의 자신을 구현할 수 있습니다. 이 책은 KernighanRitchie의 The C Programming Language ( 60 페이지) 의 첫 번째 판에 실 렸습니다 . C Programming Language ( "K & R2")의 두 번째 판에는 itoa64 페이지 의 다음 구현이 포함되어 있습니다. 가장 음수를 올바르게 처리하지 못한다 는 사실을 포함하여

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

reverse위에서 사용 된 기능 은 두 페이지 더 일찍 구현됩니다.

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

편집 : 방금 std::to_string아래의 내 기능과 동일한 작동 방식을 발견했습니다 . C ++ 11에 도입되었으며 c ++ 0x 확장자를 사용하는 경우 4.5 이상으로 최신 버전의 gcc에서 사용할 수 있습니다.


itoagcc에서 누락 되었을뿐만 아니라 버퍼를 공급해야하기 때문에 가장 편리한 기능은 아닙니다. 나는 표현에 사용될 수있는 것이 필요했기 때문에 이것을 생각해 냈습니다.

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

일반적으로 snprintf대신 사용 하는 것이 더 안전 sprintf하지만 버퍼는 오버런에 영향을받지 않도록 조심스럽게 크기가 조정됩니다.

예를 참조하십시오 : http://ideone.com/mKmZVE


Matt J가 쓴 것처럼이 itoa있지만 표준은 아닙니다. 를 사용하면 코드가 더 이식성이 뛰어납니다 snprintf.


다음 함수는 주어진 숫자의 문자열 표현을 유지하기에 충분한 메모리를 할당 한 다음 표준 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;
}

필요없는 free경우 할당 된 메모리를 늘리는 것을 잊지 마십시오 .

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

NB snprintf가 n-1 바이트를 복사하므로 snprintf (buf, len + 1, "% ld", n)를 호출해야합니다 (snprintf (buf, len, "% ld", n)만이 아님)


리눅스에서 itoa 기능은 어디에 있습니까?

Linux에는 그러한 기능이 없습니다. 대신이 코드를 사용합니다.

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

버퍼에 직접 복사 : 64 비트 정수 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];
    }

참고 : 32 비트 시스템의 경우 long에서 long long으로 변경하십시오. 32 비트 정수의 경우 int to long. m은 기수입니다. 기수를 줄이면 문자 수를 늘리십시오 (변수 i). 기수를 늘리면 문자 수를 줄이십시오 (더 나은). 서명되지 않은 데이터 유형의 경우 16 + 1이됩니다.


Archana 솔루션의 개선 된 버전이 있습니다. 기수 1-16과 숫자 <= 0에서 작동하며 메모리를 방해하지 않아야합니다.

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

itoa ()의 자체 구현을 시도했지만 이진, 8 진수, 10 진수 및 16 진수로 작동합니다.

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

인쇄하려는 경우 :

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

생계를 위해 그것을하는 사람들의 코드를 읽으면 당신에게 긴 길을 얻게 될 것입니다.

MySQL의 사람들이 어떻게했는지 확인하십시오. 소스는 매우 잘 설명되어 있으며 모든 곳에서 찾은 해킹 솔루션보다 훨씬 더 많은 것을 가르쳐 줄 것입니다.

MySQL의 int2str 구현

여기에 언급 된 구현을 제공합니다. 링크는 참조 용이며 전체 구현을 읽는 데 사용되어야합니다.

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

리눅스에서 itoa 기능은 어디에 있습니까?

itoa()C의 표준이 아니기 때문에 다양한 기능 서명을 가진 다양한 버전이 존재합니다.
char *itoa(int value, char *str, int base);* nix에서 일반적입니다.

리눅스에서 빠지거나 코드가 이식성을 제한하고 싶지 않다면 코드가 그것을 소유하게 만들 수 있습니다.

다음은 INT_MIN문제 버퍼에 문제가 없고 처리 하는 버전입니다 . NULL또는 버퍼가 충분하지 않습니다 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 = '\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);
}

다음은 모든 기본을 처리하는 C99 이상 버전입니다. [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);
}

C89 및 이후 호환 코드의 경우 내부 루프를

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

glibc 내부 구현

glibc 2.28에는 내부 구현이 있습니다.

내부에서 여러 곳에서 사용되지만 노출 될 수 있는지 또는 방법을 찾을 수 없었습니다.

적어도 그것을 기꺼이 추출하려면 강력한 구현이어야합니다.

이 질문은 자신의 롤링 방법을 묻습니다 .C에서 int를 문자열로 변환하는 방법은 무엇입니까?


RedHat 6 및 GCC 컴파일러에서 _itoa (...)를 사용했습니다. 효과가있다.


snprintf로 교체가 완료되지 않았습니다!

2, 8, 10, 16의베이스 만 다루지 만, itoa는 2와 36 사이의베이스에 적용됩니다.

base 32의 대체품을 찾고 있었기 때문에 직접 코딩해야 할 것 같습니다.


나는 이것을 선호한다 : https://github.com/wsq003/itoa_for_linux

가장 빠른 itoa () 여야합니다. 성능상의 이유로 sprintf () 대신 itoa ()를 사용하므로 기능이 제한된 가장 빠른 itoa ()가 합리적이고 가치가 있습니다.


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] = '\0';
    strrev(buffer);
}

참고 URL : https://stackoverflow.com/questions/190229/where-is-the-itoa-function-in-linux

반응형