itoa()
数値を文字列に変換するための本当に便利な関数です。Linuxにはないようですitoa()
が、同等の機能はありますsprintf(str, "%d", num)
か、それとも使用する必要がありますか?
itoa
は任意のベース変換を許可しprintf
ますが、指定子は許可しません。
gcvt()
標準ライブラリから使用しない理由はありますか?
itoa()
数値を文字列に変換するための本当に便利な関数です。Linuxにはないようですitoa()
が、同等の機能はありますsprintf(str, "%d", num)
か、それとも使用する必要がありますか?
itoa
は任意のベース変換を許可しprintf
ますが、指定子は許可しません。
gcvt()
標準ライブラリから使用しない理由はありますか?
回答:
編集:申し訳ありませんが、このマシンは明らかに非標準であり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()
。詳細については、こちらをご覧ください。あなたがしなければならないことに注意してください
#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を使用する」というアドバイスは面倒です。だからここにあなたがおそらく望んでいるものがあります:
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); }
const
修飾子は関数の戻り値の型に対しては何も行いません。コンパイラの警告をオンにすると、これがわかります:)
const char *
constへの非constポインターです。これは、非常に理にかなっており、正しいことです。
const
間にconst int f (void) { ...
してconst int* f (void) { ...
、今のコンパイラでそれを試してみました、それは理にかなっています。
itoa
は標準のC関数ではありません。独自に実装できます。これは、KernighanとRitchieの The Cプログラミング言語の最初の版に掲載されました。Cプログラミング言語の第2版( "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
上記で使用した関数は、2ページ前に実装されています。
#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で導入され、最近のバージョンのgccで利用可能です。少なくともc ++ 0x拡張機能を有効にすると、4.5から利用できます。
itoa
gccから欠落している
だけでなく、バッファーにフィードする必要があるため、これは使用するのに最も便利な関数ではありません。式で使用できるものが必要だったので、これを思いつきました。
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
std::
などのものを
次の関数は、指定された数値の文字列表現を維持するのに十分なメモリを割り当て、標準の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);
注意:snprintfはn-1バイトをコピーするため、snprintf(buf、len + 1、 "%ld"、n)を呼び出す必要があります(snprintf(buf、len、 "%ld"、n)だけではありません)
itoa
一般的な実装がitoa
実際に持っているものとは異なる振る舞いを与えます。この関数は問題ありませんが、別の名前を付けてください:) snprintf
浮動小数点文字列ではなく、バッファー長の計算に使用することもお勧めします。浮動小数点は、コーナーケースで不正確になる可能性があります。そして、callocをキャストしないでください
labs
、長い整数を取る場合に使用する必要があります。そうしないと、切り捨てられる可能性があります。
snprintf
char buf[64]
長さを取得するように固定サイズのtmpバッファーに入れてから、malloc
それにコピーします。あなたは外の任意の利益を取得していないcalloc
以上malloc
、あなたがすべてのバイトを書くことから、。非常に短い文字列の余分なコピーは、浮動小数点のlog10を呼び出さなければならないほど悪くありません。ただし、効率的なもの(bsr
x86など)に確実にインライン化するビットスキャン関数がある場合は、整数log2を使用した高速近似が役立つ場合があります。(代替案:malloc
64バイトのバッファーrealloc
、最終的な長さがわかった後)
Linuxの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;
}
私は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;
}
バッファへの直接コピー: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からlong mは基数です。基数を減らすときは、文字数を増やします(変数i)。基数を増やす場合は、文字数を減らします(より良い)。符号なしデータ型の場合、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;
}
生計を立てている人のコードを読むと、長い道のりが手に入ります。
MySQLの人がそれをどのように行ったかを確認してください。ソースは非常によくコメントされており、いたるところに見られるハッキングされたソリューション以上のものを教えてくれます。
ここで言及した実装を提供します。リンクは参照用であり、実装全体を読むために使用する必要があります。
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;
}
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 = '\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を文字列に変換する方法?
私はこれを好みます:https : //github.com/wsq003/itoa_for_linux
これは、これまでで最速のitoa()です。パフォーマンス上の理由から、sprintf()ではなくitoa()を使用しているため、機能が制限されている最速のitoa()が妥当であり、価値があります。
RedHat 6およびGCCコンパイラで_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);
}
sprintf(str, "%d", num)
?それよりはるかに遅いですitoa
か?