ฟังก์ชัน itoa ใน Linux อยู่ที่ไหน


139

itoa()เป็นฟังก์ชั่นที่ใช้งานง่ายมากในการแปลงตัวเลขเป็นสตริง Linux ดูเหมือนจะไม่มีitoa()มีฟังก์ชั่นที่เทียบเท่าหรือฉันต้องใช้sprintf(str, "%d", num)หรือไม่?


4
เหตุผลใดที่จะไม่ใช้sprintf(str, "%d", num)? มันช้ากว่าitoaไหม
javapowered

1
@ javapowered สำหรับหนึ่งitoaอนุญาตการแปลงฐานโดยพลการprintfspecifiers ไม่
vladr

@javapowered sprintf () ไม่ปลอดภัยสัญญาณ
lunesco

มีเหตุผลอะไรที่จะไม่ใช้gcvt()จากไลบรารี่มาตรฐาน?
Subin Sebastian

คำตอบ:


100

แก้ไข: ขออภัยฉันควรจำไว้ว่าเครื่องนี้ไม่ได้มาตรฐานอย่างแน่นอนเสียบเข้ากับ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>

แน่นอนคุณรู้เรื่องนี้เพราะคุณต้องการที่จะใช้ itoa()บน Linux หลังจากสันนิษฐานว่าจะใช้มันบนแพลตฟอร์มอื่น แต่ ... รหัส (ขโมยจากลิงค์ด้านบน) จะมีลักษณะ:

ตัวอย่าง

/* 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

หวังว่านี่จะช่วยได้!


1
อืมรวบรวมว่า Debian ให้ "อ้างอิงไม่ได้กับ` itoa '" อาจมีบางอย่างผิดปกติกับระบบของฉัน
Adam Pierce

ฉันได้รับเหมือนกันบน Ubuntu 8.04 ฉันสามารถหาไม่มีการอ้างอิงถึง itoa ใน stdio.h หรือ stdlib.h อย่างใดอย่างหนึ่ง (ไม่น่าแปลกใจเพราะมันไม่ได้เป็นส่วนหนึ่งของมาตรฐาน)
camh

แก้ไขเพื่อความถูกต้องขอบคุณพวก! ขอโทษฉันมักจะลืมว่านี้ไม่ได้เป็นวานิลลากล่อง Linux ;-)
แมตต์เจ

ฉันได้แก้ไขคำตอบเพื่อรวมอาร์กิวเมนต์ขนาดบัฟเฟอร์; ฉันเชื่อว่าทุกอย่างเป็นอย่างที่ควรจะเป็นตอนนี้ฉันไม่เห็นปัญหาเกี่ยวกับลำดับของการขัดแย้ง ฉันพลาดอะไรไปรึเปล่า?
Matt J

มันใช้งานไม่ได้กับ Linux? ผลลัพธ์ของคำถาม / คำตอบคืออะไร (ไม่ใช่มาตรฐานดูเหมือนจะเป็น linuxes ทั้งหมด?)

12

หากคุณกำลังเรียกมันมากคำแนะนำของ "เพียงแค่ใช้ 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); }

8
ชอบแสดงความคิดเห็นดังกล่าว :)
เจมส์ Antill

17
มันไม่ได้เป็นเพียงเธรดที่ไม่ปลอดภัย แต่ก็ไม่ปลอดภัยมาก: - ถือเป็นโมฆะ some_func (ถ่าน * a, ถ่าน * b); some_func (itoa (123), itoa (456)); สนใจที่จะเดาว่าฟังก์ชั่นรับอะไรดี?
jcoder

นอกจากนี้ผู้ที่constผ่านการรับรองจะไม่ทำอะไรกับฟังก์ชั่นส่งคืนชนิด - คุณจะรู้ว่าถ้าคุณเปิดใช้คำเตือนของคอมไพเลอร์ :)
cat

3
@cat แต่ไม่มีประเภทส่งคืนที่ผ่านการรับรองใด ๆ ที่นี่ const char *เป็นตัวชี้ที่ไม่ใช่ const ถึง const ซึ่งทำให้เข้าใจได้ง่ายและถูกต้อง
Chortos-2

1
@ Chortos-2 มันน่าสนใจแน่นอนคุณถูกต้องสมบูรณ์ - ฉันไม่ได้ตระหนักถึงความหมายที่แตกต่างในความหมายconstระหว่างconst int f (void) { ...และconst int* f (void) { ...ตอนนี้ แต่ตอนนี้ต้องลองกับคอมไพเลอร์มันสมเหตุสมผล
แมว

11

itoaไม่ใช่ฟังก์ชัน C มาตรฐาน คุณสามารถใช้งานของคุณเอง มันปรากฏในรุ่นแรกของKernighanและRitchie's The C Programming Language , หน้า 60. รุ่นที่สองของภาษา C Programming ("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;
     }
}  

8

แก้ไข:ฉันเพิ่งค้นพบเกี่ยวกับstd::to_stringสิ่งที่เหมือนกันในการทำงานกับฟังก์ชั่นของฉันเองด้านล่าง มันถูกนำมาใช้ใน C ++ 11 และมีให้บริการใน gcc รุ่นล่าสุดอย่างน้อยก็เร็วที่สุดเท่าที่ 4.5 หากคุณเปิดใช้งานส่วนขยาย c ++ 0x


ไม่เพียง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


12
คำถามที่น่าจะเป็นเกี่ยวกับ C ซึ่งไม่มีstd::สิ่งอื่น ๆ
glglgl


4

ฟังก์ชั่นดังต่อไปนี้จัดสรรหน่วยความจำเพียงพอที่จะให้การแสดงสตริงของจำนวนที่กำหนดแล้วเขียนการเป็นตัวแทนสตริงลงในพื้นที่นี้โดยใช้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))


4
ไม่ใช่ความคิดที่ดีที่จะเรียกใช้ฟังก์ชันของคุณitoaแต่ให้พฤติกรรมที่แตกต่างกับการใช้งานทั่วไปที่itoaมีอยู่จริง ฟังก์ชั่นนี้เป็นแนวคิดที่ดี แต่ก็เรียกมันว่าอย่างอื่น :) ฉันขอแนะนำให้ใช้snprintfในการคำนวณความยาวของบัฟเฟอร์แทนสตริงจุดลอยตัว จุดลอยตัวอาจมีตัวเรือนมุมไม่ถูกต้อง และอย่าใช้คำสั่ง calloc
MM

ขอบคุณสำหรับคำแนะนำ
mmdemirbas

ควรใช้labsถ้ามันจะเป็นจำนวนเต็มยาว มิฉะนั้นอาจตัดทอน
Schwern

snprintfลงในบัฟเฟอร์ tmp ขนาดคงที่char buf[64]เพื่อให้ได้ความยาวจากนั้นmallocคัดลอกลงไป คุณจะไม่ได้รับผลประโยชน์ใด ๆ จากส่วนcallocเกินmallocเนื่องจากคุณเขียนไบต์ทั้งหมด การคัดลอกสตริงที่สั้นมากเป็นพิเศษนั้นน้อยกว่าการเรียกจุดลอยตัว log10 ประมาณได้อย่างรวดเร็วด้วยการ log2 จำนวนเต็มอาจจะมีประโยชน์ แต่ถ้าคุณมีฟังก์ชั่นบิตสแกนที่จะเชื่อถือได้แบบอินไลน์บางสิ่งบางอย่างที่มีประสิทธิภาพ (เช่นbsrบน x86) (ทางเลือก: mallocบัฟเฟอร์ 64 ไบต์และreallocหลังจากที่คุณทราบความยาวสุดท้าย)
Peter Cordes

3

ฟังก์ชัน itoa ใน Linux อยู่ที่ไหน

ไม่มีฟังก์ชั่นดังกล่าวใน 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;
}

คุณควรแก้ไขคำตอบของคุณเพื่ออธิบายว่ารหัสนี้ตอบคำถามอย่างไร
C. Helling

2

ฉันพยายามใช้งาน 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] = '\0';
            strcpy(str,buf);
            break;
        default:
            return NULL;
    }
    return str;
}

1

คัดลอกโดยตรงไปยังบัฟเฟอร์: เลขจำนวนเต็ม 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 บิต ยาวไปจนถึง int ในกรณีที่เป็นจำนวนเต็ม 32 บิต m คือฐาน เมื่อลด radix ให้เพิ่มจำนวนอักขระ (ตัวแปร i) เมื่อเพิ่ม radix ให้ลดจำนวนอักขระ (ดีกว่า) ในกรณีที่ประเภทข้อมูลที่ไม่ได้ลงนามฉันเพิ่งจะกลายเป็น 16 + 1


1

นี่คือโซลูชันของ Archana ที่ได้รับการปรับปรุงให้ดีขึ้นมาก มันใช้งานได้สำหรับ Radix 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;
}

1

หากคุณต้องการพิมพ์:

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");
} 

1

การอ่านรหัสของคนที่ทำเพื่อหาเลี้ยงชีพคุณจะได้รับทางยาว

ตรวจสอบว่าผู้ชายจาก MySQL ทำมันได้อย่างไร แหล่งที่มาแสดงความคิดเห็นได้ดีมากและจะสอนคุณมากกว่าการแฮ็กโซลูชันที่พบได้ทั่วทุกที่

การใช้งาน int2str ของ 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;
}

1
ยินดีต้อนรับลิงก์ไปยังโซลูชันที่เป็นไปได้ แต่โปรดเพิ่มบริบทรอบลิงก์เพื่อให้ผู้ใช้เพื่อนของคุณมีความคิดว่ามันคืออะไรและเพราะเหตุใด อ้างถึงส่วนที่เกี่ยวข้องที่สุดของลิงค์สำคัญเสมอในกรณีที่เว็บไซต์เป้าหมายไม่สามารถเข้าถึงหรือออฟไลน์อย่างถาวร คำนึงถึงว่าการเชื่อมโยงไปยังเว็บไซต์ภายนอกเป็นเพียงเหตุผลที่เป็นไปได้ว่าเป็นเพราะเหตุใดและคำตอบบางคำตอบถูกลบไปอย่างไร .
Tunaki

1
ดังนั้นสิ่งที่ดีเกี่ยวกับตัวอย่างที่คุณโพสต์ที่นี่ สิ่งที่ผู้อ่านในอนาคตควรระวัง
Martijn Pieters

1

ฟังก์ชัน itoa ใน Linux อยู่ที่ไหน

เนื่องจากitoa()ไม่ใช่มาตรฐานใน C เวอร์ชันต่าง ๆ ที่มีลายเซ็นของฟังก์ชันต่าง ๆ จะมีอยู่
char *itoa(int value, char *str, int base);เป็นเรื่องปกติใน * ระวัง

หากมันหายไปจาก Linux หรือหากรหัสไม่ต้องการ จำกัด การพกพารหัสอาจทำให้มันเป็นของตัวเอง

ด้านล่างนี้เป็นรุ่นที่ไม่ได้มีปัญหากับINT_MINและบัฟเฟอร์ปัญหาจับ: หรือผลตอบแทนบัฟเฟอร์ไม่เพียงพอNULLNULL

#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);

1

การใช้งานภายใน glibc

glibc 2.28 มีการใช้งานภายใน:

ซึ่งใช้ในหลายสถานที่ภายใน แต่ฉันไม่พบว่ามันจะถูกเปิดเผยหรือไม่

อย่างน้อยก็ควรเป็นการใช้งานที่มีประสิทธิภาพหากคุณยินดีที่จะแยก

คำถามนี้ถามวิธีม้วนตัวเอง: วิธีการแปลง int เป็นสายอักขระใน C?


1

ฉันต้องการสิ่งนี้: https://github.com/wsq003/itoa_for_linux

มันควรจะเป็น itoa ที่เร็วที่สุด () เลยทีเดียว เราใช้ itoa () แทน sprintf () เพื่อเหตุผลด้านประสิทธิภาพดังนั้น itoa ที่เร็วที่สุด () ที่มีคุณสมบัติ จำกัด นั้นสมเหตุสมผลและคุ้มค่า



0

การแทนที่ด้วย snprintf ไม่สมบูรณ์!

มันครอบคลุมเฉพาะฐาน: 2, 8, 10, 16 ในขณะที่ itoa ทำงานสำหรับฐานระหว่าง 2 และ 36

เนื่องจากฉันค้นหาแทนที่ฐาน 32 ฉันเดาว่าฉันจะต้องเขียนโค้ดของตัวเอง


-4

คุณสามารถใช้โปรแกรมนี้แทน 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);
}

4
มีข้อบกพร่องมากมายในรหัสนี้: 1) ไม่แปลงฐานสิบหกอย่างถูกต้อง 2) ไม่แปลง 0 เลย 3) ไม่ทำงานกับจำนวนลบ 4) ไม่มีการตรวจสอบบัฟเฟอร์โอเวอร์รัน ฉันจะโพสต์รุ่นปรับปรุงของรหัสนี้ในไม่ช้า
Chris Desjardins
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.