Linux中的itoa功能在哪里?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux中的itoa功能在哪里?相关的知识,希望对你有一定的参考价值。

itoa()是一个非常方便的函数,可以将数字转换为字符串。 Linux似乎没有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()那么简洁或酷,但至少你可以写一次,随处运行(tm);-)

这是旧的(编辑过的)答案

你是正确的说明默认的gcc libc不包括itoa(),就像其他几个平台一样,因为它在技术上并不属于标准的一部分。有关更多信息,请参阅here。请注意,你必须

#include <stdlib.h>

当然你已经知道了这一点,因为你想在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
",buffer);
  itoa (i,buffer,16);
  printf ("hexadecimal: %s
",buffer);
  itoa (i,buffer,2);
  printf ("binary: %s
",buffer);
  return 0;
}

输出:

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

希望这可以帮助!

另一答案

我尝试了我自己的itoa()实现,它似乎是二进制,八进制,十进制和十六进制

#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] = '';
            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("
");
} 
另一答案

阅读那些以此为生的人的代码会让你有一个很长的路要走。

看看mysql的人是怎么做到的。来源是非常好的评论,并将教你比在整个地方发现的黑客攻击解决方案更多。

MySQL's implementation of 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 = '';
  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;
}
另一答案

Linux中的itoa功能在哪里?

由于itoa()在C中不是标准的,因此存在具有各种功能签名的各种版本。 char *itoa(int value, char *str, int base);在* nix中很常见。

如果Linux中缺少它或者代码不想限制可移植性,代码可以使它自己。

下面是一个没有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 = '';
  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 = '';
  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有一个内部实现: