【问题标题】:Converting int to string in C在 C 中将 int 转换为字符串
【发布时间】:2011-07-11 16:21:20
【问题描述】:

我正在使用itoa() 函数将int 转换为string,但它给出了错误:

undefined reference to `itoa'
collect2: ld returned 1 exit status

是什么原因?是否有其他方法可以执行此转换?

【问题讨论】:

标签: c


【解决方案1】:

使用snprintf,它比itoa更便携。

itoa is not part of standard C, nor is it part of standard C++;但是,很多编译器和相关库都支持它。

sprintf 的示例

char* buffer = ... allocate a buffer ...
int value = 4564;
sprintf(buffer, "%d", value);

snprintf 的示例

char buffer[10];
int value = 234452;
snprintf(buffer, 10, "%d", value);

这两个函数都类似于fprintf,但输出被写入数组而不是流。 sprintfsnprintf 之间的区别在于,snprintf 通过写入最多可存储在 buffer 中的最大字符数来保证缓冲区不会溢出。

【讨论】:

  • 你能帮忙举个例子吗
  • 现在你有一个或两个例子。
  • sprintfsnprintf 之间的另一个区别是它们在标准中描述:C89(及更高版本)为sprintf;用于 snprintf 的 C99。值得注意的是,Windows 库缺少 snprintf 函数或具有与标准描述不同的行为。
  • SAVED ME at 2:08 a.m. 我的编译器出现问题,因为它不支持 itoa ,谢谢。
  • snprintfputting '\0' 是我数组的最后一个元素吗?所以我可以知道它在哪里结束?
【解决方案2】:

通常snprintf() 是要走的路:

char str[16]; // could be less but i'm too lazy to look for the actual the max length of an integer
snprintf(str, sizeof(str), "%d", your_integer);

【讨论】:

    【解决方案3】:

    更好地使用 sprintf(),

    char stringNum[20];
    int num=100;
    sprintf(stringNum,"%d",num);
    

    【讨论】:

    • 50 有点矫枉过正——即使是 64 位整数也不需要 49 个字符。并且您的 sprintf 调用中有错字
    • 次要:char stringNum[21]; 需要 -power(2,63)
    • 我认为在这种情况下值得一提的是,对于新手和专业人士来说,使用固定缓冲区大小和sprintf 被认为是不好的做法,也是最糟糕的做法之一内存损坏、安全问题/漏洞和其他奇怪错误的常见根本原因。如果可能,请在将字符串格式化为缓冲区时始终使用snprintf,并确保跟踪所用缓冲区的大小(还要考虑尾随的 \0!)
    【解决方案4】:

    看这个例子

    #include <stdlib.h> // for itoa() call
    #include <stdio.h>  
    
    int main() {
        int num = 145;
        char buf[5];
    
        // convert 123 to string [buf]
        itoa(num, buf, 10);
    
        // print our string
        printf("%s\n", buf);
    
        return 0;
    }
    

    看到这个link 有其他例子。

    【讨论】:

    【解决方案5】:

    像 Edwin 建议的那样,使用 snprintf

    #include <stdio.h>
    int main(int argc, const char *argv[])
    {
        int n = 1234;
        char buf[10];
        snprintf(buf, 10, "%d", n);
        printf("%s\n", buf);
        return 0;
    }
    

    【讨论】:

      【解决方案6】:

      如果您真的想使用 itoa,则需要包含标准库头文件。

      #include <stdlib.h>
      

      我还相信,如果您使用的是 Windows(使用 MSVC),那么 itoa 实际上就是 _itoa

      http://msdn.microsoft.com/en-us/library/yakksftt(v=VS.100).aspx

      再说一次,既然您收到了来自collect2 的消息,那么您很可能在 *nix 上运行 GCC。

      【讨论】:

        【解决方案7】:

        在继续之前,我必须警告您itoa 不是 ANSI 函数——它不是标准的 C 函数。您应该使用sprintfint 转换为字符串。

        itoa 接受三个参数。

        • 第一个是要转换的整数。
        • 第二个是指向字符数组的指针 - 这是字符串将被存储的位置。如果你传入一个char * 变量,程序可能会崩溃,所以你应该传入一个正常大小的字符数组,它会正常工作。
        • 最后一个不是数组的大小,而是您的数字的 BASE - 以 10 为底的数字是您最有可能使用的。

        函数返回一个指向它的第二个参数的指针——它存储了转换后的字符串。

        itoa 是一个非常有用的函数,它被一些编译器支持 - 很遗憾它并没有被所有编译器支持,不像 atoi

        如果你仍然想使用itoa,这里是你应该如何使用它。否则,您可以选择使用sprintf(只要您想要以 8、10 或 16 为基数的输出):

        char str[5];
        printf("15 in binary is %s\n",  itoa(15, str, 2));
        

        【讨论】:

          【解决方案8】:

          您可以使用此功能制作自己的itoa

          void my_utoa(int dataIn, char* bffr, int radix){
          int temp_dataIn;
          temp_dataIn = dataIn;
          int stringLen=1;
          
          while ((int)temp_dataIn/radix != 0){
              temp_dataIn = (int)temp_dataIn/radix;
              stringLen++;
          }
          //printf("stringLen = %d\n", stringLen);
          temp_dataIn = dataIn;
          do{
              *(bffr+stringLen-1) = (temp_dataIn%radix)+'0';
              temp_dataIn = (int) temp_dataIn / radix;
          }while(stringLen--);}
          

          这是一个例子:

          char buffer[33];
          int main(){
            my_utoa(54321, buffer, 10);
            printf(buffer);
            printf("\n");
          
            my_utoa(13579, buffer, 10);
            printf(buffer);
            printf("\n");
          }
          

          【讨论】:

          • 我很确定这不会像 itoa 那样工作,因为没有代码可以处理以 10 为底的负数。
          【解决方案9】:
          void itos(int value, char* str, size_t size) {
              snprintf(str, size, "%d", value);
          }
          

          ..与call by reference 一起使用。像这样使用它,例如:

          int someIntToParse;
          char resultingString[length(someIntToParse)];
          
          itos(someIntToParse, resultingString, length(someIntToParse));
          

          现在resultingString 将保存你的 C-'string'。

          【讨论】:

          • 这仅适用于十进制(base 10)转换。
          【解决方案10】:

          使用snprintf - 它是每个编译器中的标准配置。通过使用NULL, 0 参数调用它来查询它所需的大小。最后为null多分配一个字符。

          int length = snprintf( NULL, 0, "%d", x );
          char* str = malloc( length + 1 );
          snprintf( str, length + 1, "%d", x );
          ...
          free(str);
          

          【讨论】:

            【解决方案11】:
            char string[something];
            sprintf(string, "%d", 42);
            

            【讨论】:

              【解决方案12】:

              与 Ahmad Sirojuddin 的实现类似,但语义略有不同。从安全的角度来看,任何时候函数写入字符串缓冲区,函数都应该真正“知道”缓冲区的大小并拒绝写入超过缓冲区的末尾。我猜这是您再也找不到 itoa 的部分原因。

              另外,下面的实现避免了两次执行模块/除法操作。

              char *u32todec( uint32_t    value,
                              char        *buf,
                              int         size)
              {
                  if(size > 1){
                      int i=size-1, offset, bytes;
                      buf[i--]='\0';
                      do{
                          buf[i--]=(value % 10)+'0';
                          value = value/10;
                      }while((value > 0) && (i>=0));
                      offset=i+1;
                      if(offset > 0){
                          bytes=size-i-1;
                          for(i=0;i<bytes;i++)
                              buf[i]=buf[i+offset];
                      }
                      return buf;
                  }else
                      return NULL;
              }
              

              下面的代码既测试了上面的代码,又证明了它的正确性:

              int main(void)
              {
                  uint64_t acc;
                  uint32_t inc;
                  char buf[16];
                  size_t bufsize;
                  for(acc=0, inc=7; acc<0x100000000; acc+=inc){
                      printf("%u: ", (uint32_t)acc);
                      for(bufsize=17; bufsize>0; bufsize/=2){
                          if(NULL != u32todec((uint32_t)acc, buf, bufsize))
                              printf("%s ", buf);
                      }
                      printf("\n");
                      if(acc/inc > 9)
                          inc*=7;
                  }
                  return 0;
              }
              

              【讨论】:

                【解决方案13】:

                itoa() 函数未在 ANSI-C 中定义,因此某些平台默认未实现 (Reference Link)。

                s(n)printf() 函数是 itoa() 的最简单替换。但是itoa(integer to ascii)函数可以作为整数到ascii转换问题的一个更好的整体解决方案。

                itoa() 的性能也优于 s(n)printf(),具体取决于实现。以简化的 itoa(仅支持 10 个基数)实现为例:Reference Link

                下面是另一个完整的 itoa() 实现 (Reference Link):

                #include <stdbool.h> 
                #include <string.h>
                
                // A utility function to reverse a string 
                char *reverse(char *str)
                {
                  char *p1, *p2;
                
                  if (! str || ! *str)
                        return str;
                  for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
                  {
                        *p1 ^= *p2;
                        *p2 ^= *p1;
                        *p1 ^= *p2;
                  }
                  return str;
                }
                // Implementation of itoa() 
                char* itoa(int num, char* str, int base) 
                { 
                    int i = 0; 
                    bool isNegative = false; 
                  
                    /* Handle 0 explicitely, otherwise empty string is printed for 0 */
                    if (num == 0) 
                    { 
                        str[i++] = '0'; 
                        str[i] = '\0'; 
                        return str; 
                    } 
                  
                    // In standard itoa(), negative numbers are handled only with  
                    // base 10. Otherwise numbers are considered unsigned. 
                    if (num < 0 && base == 10) 
                    { 
                        isNegative = true; 
                        num = -num; 
                    } 
                  
                    // Process individual digits 
                    while (num != 0) 
                    { 
                        int rem = num % base; 
                        str[i++] = (rem > 9)? (rem-10) + 'a' : rem + '0'; 
                        num = num/base; 
                    } 
                  
                    // If number is negative, append '-' 
                    if (isNegative) 
                        str[i++] = '-'; 
                  
                    str[i] = '\0'; // Append string terminator 
                  
                    // Reverse the string 
                    reverse(str); 
                  
                    return str; 
                } 
                

                另一个完整的 itoa() 实现:Reference Link

                下面的 itoa() 用法示例 (Reference Link):

                #include <stdio.h>
                #include <stdlib.h>
                #include <string.h>
                 
                int main()
                {
                    int a=54325;
                    char buffer[20];
                    itoa(a,buffer,2);   // here 2 means binary
                    printf("Binary value = %s\n", buffer);
                 
                    itoa(a,buffer,10);   // here 10 means decimal
                    printf("Decimal value = %s\n", buffer);
                 
                    itoa(a,buffer,16);   // here 16 means Hexadecimal
                    printf("Hexadecimal value = %s\n", buffer);
                    return 0;
                }
                

                【讨论】:

                  【解决方案14】:
                  if(InNumber == 0)
                  {
                      return TEXT("0");
                  }
                  
                  const int32 CharsBufferSize = 64; // enought for int128 type
                  TCHAR ResultChars[CharsBufferSize];
                  int32 Number = InNumber;
                  
                  // Defines Decreasing/Ascending ten-Digits to determine each digit in negative and positive numbers.
                  const TCHAR* DigitalChars = TEXT("9876543210123456789");
                  constexpr int32 ZeroCharIndex = 9; // Position of the ZERO character from the DigitalChars.
                  constexpr int32 Base = 10; // base system of the number.
                  
                  // Convert each digit of the number to a digital char from the top down.
                  int32 CharIndex = CharsBufferSize - 1;
                  for(; Number != 0 && CharIndex > INDEX_NONE; --CharIndex)
                  {
                      const int32 CharToInsert = ZeroCharIndex + (Number % Base);
                      ResultChars[CharIndex] = DigitalChars[CharToInsert];
                      Number /= Base;
                  }
                  
                  // Insert sign if is negative number to left of the digital chars.
                  if(InNumber < 0 && CharIndex > INDEX_NONE)
                  {
                      ResultChars[CharIndex] = L'-';
                  }
                  else
                  {
                      // return to the first digital char if is unsigned number.
                      ++CharIndex;
                  }
                  
                  // Get number of the converted chars and construct string to return.
                  const int32 ResultSize = CharsBufferSize - CharIndex;
                  return TString{&ResultChars[CharIndex], ResultSize};
                  

                  【讨论】:

                  • 如果您能解释答案而不是只发布代码,那就太好了。
                  猜你喜欢
                  • 2013-05-23
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-10-29
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多