itoa()
숫자를 문자열로 변환하는 정말 편리한 함수입니다. 리눅스에는없는 것 같습니다 itoa()
. 동등한 기능이 sprintf(str, "%d", num)
있습니까? 아니면 사용해야 합니까?
itoa
는 임의의 기본 변환을 허용하지만 printf
지정자는 허용 하지 않습니다.
gcvt()
표준 라이브러리에서 사용하지 않는 이유는 무엇입니까?
itoa()
숫자를 문자열로 변환하는 정말 편리한 함수입니다. 리눅스에는없는 것 같습니다 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()
있지만 적어도 한 번만 쓸 수 있습니다 .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); }
const
한정자는 함수 반환 유형에 대해 아무 것도 수행하지 않습니다. 컴파일러 경고를 켠 경우이를 알 수 있습니다. :)
const char *
const에 대한 비 const 포인터입니다. 이는 많은 의미가 있고 정확합니다.
const
사이 const int f (void) { ...
와 const int* f (void) { ...
는 의미가, 컴파일러와 함께 그것을 시도하는 데 지금 만합니다.
itoa
표준 C 함수가 아닙니다. 당신은 당신의 자신을 구현할 수 있습니다. 이 책은 Kernighan 과 Ritchie의 The C Programming Language ( 60 페이지) 의 첫 번째 판에 실 렸습니다 . C Programming Language ( "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;
}
}
편집 : 방금 std::to_string
아래에서 내 기능과 동일한 작동 방식을 발견했습니다 . C ++ 11에 도입되었으며 c ++ 0x 확장자를 사용하는 경우 4.5 이상으로 최신 버전의 gcc에서 사용할 수 있습니다.
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);
NB 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
over의 이점을 얻지 못합니다 malloc
. 매우 짧은 문자열의 추가 복사는 부동 소수점 log10을 호출하는 것보다 덜 나쁩니다. 그래도 bsr
x86에서 와 같이 효율적으로 무언가를 인라인 할 수있는 비트 스캔 기능이 있다면 정수 log2를 사용한 빠른 근사치가 유용 할 수 있습니다 . (대안 : malloc
64 바이트 버퍼 및 realloc
최종 길이를 알고 난 후)
리눅스에서 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 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;
}
생계를 위해 그것을하는 사람의 코드를 읽으면 당신에게 긴 길을 얻게 될 것입니다.
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;
}
리눅스에서 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를 문자열로 변환하는 방법은 무엇입니까?
나는 이것을 선호한다 : 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);
}
sprintf(str, "%d", num)
무엇입니까? 보다 느리게 진행itoa
됩니까?