在C语言中将整数转换为字符串

43

我正在使用 itoa() 函数将一个 int 转换为 string,但是出现了错误:

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

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


是的,我已经包含了 stdlib.h 头文件,但仍然无法正常工作。 - Shweta
可能是 如何在 C 中将 int 转换为字符串 的重复问题。 - Ciro Santilli OurBigBook.com
14个回答

88
使用snprintf更加便携,比使用itoa更可靠。itoa 不是 C 标准库或者 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通过写入缓冲区可以存储的最大字符数来保证不会发生缓冲区溢出。


1
sprintfsnprintf之间的另一个区别是它们所描述的标准:sprintf适用于C89(及更高版本);snprintf适用于C99。值得注意的是,Windows库缺少snprintf函数或其行为与标准描述不同。 - pmg
snprintf是否将'\0'放置在我的数组最后一个元素中?这样我就可以知道它在哪里结束了? - Silidrone
@MuhamedCicak 如果写入的值和终止符'\0'可以适应size参数,则会添加终止符'\0'。您应该检查返回值,以查看它是否等于输入的大小或更大。如果它等于输入的大小或更大,则结果被截断,缓冲区可能没有终止符'\0'字符。 - Edwin Buck
@EdwinBuck 这是正确的,但为了进一步澄清,我会说即使发生“截断”,你仍然会有一个 '\0'(除非你提供了大小为零的尺寸,但这种用法只有在确定需要缓冲区大小之前进行第二次调用时才有意义)。为了完全正确,还需要检查返回值是否为负数,这种情况发生在“发生编码错误”时(不管那意味着什么)。在出现错误的情况下,没有任何规定缓冲区至少会以 '\0' 开头,当尝试使用它时可能会出现可怕的后果! - Johan Boulé

9

请使用snprintf函数,该函数是标准的,并且在每个编译器中都可用。通过使用NULL, 0参数调用该函数以查询所需的大小。为字符串末尾的空字符分配一个额外的字符。

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

8
在我继续之前,我必须警告你,itoa 不是 ANSI 函数 - 它不是标准的 C 函数。你应该使用 sprintf 将一个 int 转换成一个字符串。 itoa 接受三个参数。
第一个参数是要转换的整数。
第二个参数是一个指向字符数组的指针 - 这是字符串将要被存储的地方。如果你传递一个 char * 变量,程序可能会崩溃,所以你应该传递一个正常大小的 char 数组,它会很好地工作。
最后一个参数不是数组的大小,而是你的数字的基数 - 十进制是你最有可能使用的。
函数返回指向其第二个参数的指针 - 它存储了转换后的字符串。 itoa 是一个非常有用的函数,由一些编译器支持 - 很可惜不像 atoi 那样被所有编译器支持。
如果你仍然想使用 itoa,这里是如何使用它。否则,你还有另一个选择,使用 sprintf(只要你想要输出 8、10 或 16 进制):
char str[5];
printf("15 in binary is %s\n",  itoa(15, str, 2));

4
更好的选择是使用sprintf()函数。
char stringNum[20];
int num=100;
sprintf(stringNum,"%d",num);

50有点过头了——即使是64位整数也不需要49个字符。而且你的sprintf调用中有一个错别字。 - ThiefMaster
2
小问题:char stringNum[21];-power(2,63) 操作中需要。 - chux - Reinstate Monica
我认为在这个背景下,无论是新手还是专业人士,值得一提的是,使用固定缓冲区大小和sprintf被认为是“不良实践”,也是内存损坏、安全问题/漏洞和其他奇怪错误的最常见根本原因之一。如果可能的话,每当您将字符串格式化到缓冲区时,请始终使用snprintf,并确保您跟踪所使用的缓冲区的大小(还要考虑尾随\0!) - origo

3
你可以使用以下函数制作自己的 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");
}

我非常确定这会不起作用,因为没有处理 10 进制负数的代码。 - Dmitry Grigoryev

3
通常情况下,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);

2
char string[something];
sprintf(string, "%d", 42);

2
void itos(int value, char* str, size_t size) {
    snprintf(str, size, "%d", value);
}

..与 按引用传递 一起工作。例如这样使用:

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

itos(someIntToParse, resultingString, length(someIntToParse));

现在resultingString将保存你的C-“字符串”。

1
这仅适用于十进制(基数10)转换。 - microMolvi

1
与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;
}

0

看这个例子

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

看看这个链接,其中有其他的例子。


请查看此链接,其中包含一些示例:http://www.daniweb.com/software-development/c/threads/11049 - Ishu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接