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有一个内部实现: