Linux中的itoa函数在哪里?
itoa()
是一个非常方便的函数,将数字转换为string。 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()
那样简洁或者酷,但是至less你可以写一次,随处运行(tm);-)
这是旧的(编辑的)答案
你是正确的说明默认的gcc libc
不包含itoa()
,就像其他几个平台一样,因为它在技术上并不是标准的一部分。 在这里看到更多的信息。 请注意,你必须
#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\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”的build议可能会很烦人。 所以这是你可能想要的:
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); }
编辑:我刚刚发现了std::to_string
这是相同的操作,以我自己的函数下面。 它是在C ++ 11中引入的,并且在最新版本的gcc中可用,至less早在4.5版本中,如果启用c ++ 0x扩展。
不仅是gcc缺lessitoa
,它不是使用最方便的函数,因为你需要为它提供一个缓冲区。 我需要一些可以在expression式中使用的东西,所以我想出了这个:
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
正如马特·J写的,有itoa
,但这不是标准的。 如果您使用snprintf
您的代码将更具可移植性。
itoa
不是一个标准的C函数。 你可以实现你自己的。 它出现在Kernighan和Ritchie的 The C Programming Language的第一版中,第60页。C编程语言(“K&R2”)的第二版包含下面的itoa
实现,第64页。本书注意到这个问题实现,包括它没有正确处理最负数的事实
/* 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; } }
下面的函数分配足够的内存来保持给定数字的string表示,然后使用标准sprintf
方法将string表示写入该区域。
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))
直接复制到缓冲区:64位整数itoahex:
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位机器长久更改。 在32位整数的情况下长整型为int。 m是基数。 当减小基数时,增加字符数(variablesi)。 增加基数时,减less字符数(更好)。 在无符号数据types的情况下,我只是变成了16 + 1。
这是Archana解决scheme的一个大大改进的版本。 它适用于任何基数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()的实现,它似乎在二进制,八进制,十进制和hex工作
#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[ni-1] ='1'; } else { buf[ni-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"); }
我在RedHat 6和GCC编译器上使用了_itoa(…)。 有用。
由于itoa()
在C中不是标准的,因此存在具有各种function签名的各种版本。 char * itoa (int value, char *str, int base);
在* nix中很常见。
如果它从Linux丢失或如果代码不想限制可移植性,代码可以使它自己。
下面是一个版本,没有INT_MIN
和处理问题缓冲区的问题: NULL
或缓冲区不足返回NULL
。
#include <stdlib.h> #include <limits.h> #include <string.h> // Buffer size for a decimal string of a signed integer, 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); }
Linux中的itoa函数在哪里?
Linux中没有这样的function。 我使用这个代码。
/* ============= 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 (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; }
阅读那些为了谋生的家伙的代码会给你一个很长的路要走。
看看如何从MySQL的人做到这一点。 来源是非常好的意见,并会教你不仅仅是破解find遍布各地的解决scheme。
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; }
你可以用这个程序代替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); }