【发布时间】:2011-07-11 16:21:20
【问题描述】:
我正在使用itoa() 函数将int 转换为string,但它给出了错误:
undefined reference to `itoa'
collect2: ld returned 1 exit status
是什么原因?是否有其他方法可以执行此转换?
【问题讨论】:
-
是的,我已经包含了 stdlib.h,但它仍然无法正常工作
标签: c
我正在使用itoa() 函数将int 转换为string,但它给出了错误:
undefined reference to `itoa'
collect2: ld returned 1 exit status
是什么原因?是否有其他方法可以执行此转换?
【问题讨论】:
标签: c
使用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,但输出被写入数组而不是流。 sprintf 和 snprintf 之间的区别在于,snprintf 通过写入最多可存储在 buffer 中的最大字符数来保证缓冲区不会溢出。
【讨论】:
sprintf 和 snprintf 之间的另一个区别是它们在标准中描述:C89(及更高版本)为sprintf;用于 snprintf 的 C99。值得注意的是,Windows 库缺少 snprintf 函数或具有与标准描述不同的行为。
snprintfputting '\0' 是我数组的最后一个元素吗?所以我可以知道它在哪里结束?
通常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);
【讨论】:
更好地使用 sprintf(),
char stringNum[20];
int num=100;
sprintf(stringNum,"%d",num);
【讨论】:
char stringNum[21]; 需要 -power(2,63)。
sprintf 被认为是不好的做法,也是最糟糕的做法之一内存损坏、安全问题/漏洞和其他奇怪错误的常见根本原因。如果可能,请在将字符串格式化为缓冲区时始终使用snprintf,并确保跟踪所用缓冲区的大小(还要考虑尾随的 \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;
}
看到这个link 有其他例子。
【讨论】:
像 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;
}
【讨论】:
如果您真的想使用 itoa,则需要包含标准库头文件。
#include <stdlib.h>
我还相信,如果您使用的是 Windows(使用 MSVC),那么 itoa 实际上就是 _itoa。
见http://msdn.microsoft.com/en-us/library/yakksftt(v=VS.100).aspx
再说一次,既然您收到了来自collect2 的消息,那么您很可能在 *nix 上运行 GCC。
【讨论】:
在继续之前,我必须警告您itoa 不是 ANSI 函数——它不是标准的 C 函数。您应该使用sprintf 将int 转换为字符串。
itoa 接受三个参数。
char * 变量,程序可能会崩溃,所以你应该传入一个正常大小的字符数组,它会正常工作。函数返回一个指向它的第二个参数的指针——它存储了转换后的字符串。
itoa 是一个非常有用的函数,它被一些编译器支持 - 很遗憾它并没有被所有编译器支持,不像 atoi。
如果你仍然想使用itoa,这里是你应该如何使用它。否则,您可以选择使用sprintf(只要您想要以 8、10 或 16 为基数的输出):
char str[5];
printf("15 in binary is %s\n", itoa(15, str, 2));
【讨论】:
您可以使用此功能制作自己的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 为底的负数。
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'。
【讨论】:
使用snprintf - 它是每个编译器中的标准配置。通过使用NULL, 0 参数调用它来查询它所需的大小。最后为null多分配一个字符。
int length = snprintf( NULL, 0, "%d", x );
char* str = malloc( length + 1 );
snprintf( str, length + 1, "%d", x );
...
free(str);
【讨论】:
char string[something];
sprintf(string, "%d", 42);
【讨论】:
与 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;
}
【讨论】:
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;
}
【讨论】:
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};
【讨论】: