我刚开始学习 C 语言。
我正在寻找一个将 int
转换成字符串的函数示例。我发现 itoa
,但这不是标准 C 的一部分。
我还找到了 sprintf(str, "%d", aInt);
,但问题是我不知道所需 str 的大小。那么,我应该如何传递正确的输出字符串大小呢?
我刚开始学习 C 语言。
我正在寻找一个将 int
转换成字符串的函数示例。我发现 itoa
,但这不是标准 C 的一部分。
我还找到了 sprintf(str, "%d", aInt);
,但问题是我不知道所需 str 的大小。那么,我应该如何传递正确的输出字符串大小呢?
有最佳的方法来适当地调整数组大小,以考虑 sizeof(int)
的差异,但是乘以 4 对于十进制足够了。对于 sizeof(int)==1
的边缘情况需要加上 +1。
int x; // assign a value to x
char buffer[sizeof(int) * 4 + 1];
sprintf(buffer, "%d", x);
如果您需要从函数返回字符串指针,应该分配缓冲区而不是使用堆栈内存:
char* integer_to_string(int x)
{
char* buffer = malloc(sizeof(char) * sizeof(int) * 4 + 1);
if (buffer)
{
sprintf(buffer, "%d", x);
}
return buffer; // caller is expected to invoke free() on this buffer to release memory
}
malloc()
等,这更难)。如果你传递了数组,请同时传递大小,并在函数内部使用snprintf()
来确保安全。如果你这样做,应该检查溢出错误,但是大多数函数都应该进行错误检查。 - Jonathan Lefflersizeof(int) == 1
,那么您需要将分配的大小增加1,以便负数可以与空终止符一起适合。实际上,sizeof(int)
总是 > 1
,因此不需要这样做。 - selbiesizeof(int)==1
的系统(它们具有最小可寻址单元为16位或32位)。我猜代码应该是 sizeof(int) * CHAR_BIT / 2
。 - M.M在便携式C中,最简单的方法是使用snprintf
来计算所需数组的大小,然后使用sprintf
进行实际转换。例如:
char buffer[snprintf(NULL, 0, "%d", x) + 1];
sprintf(buffer, "%d", x);
CHAR_BIT
不为8的环境(例如,一些DSP使用16位或32位字节)中,您需要更改乘数。CHAR_BIT
确保可移植性,即使CHAR_BIT
发生变化。它被呈现为宏,因此它具有内部文档功能;它告诉您高级别描述是什么,而仅仅使用乘法无法做到这一点。#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#define digit_count(num) (1 /* sign */ \
+ sizeof (num) * CHAR_BIT / 3 /* digits */ \
+ (sizeof (num) * CHAR_BIT % 3 > 0)/* remaining digit */ \
+ 1) /* NUL terminator */
int main(void) {
short short_number = -32767;
int int_number = 32767;
char short_buffer[digit_count(short_number)] = { 0 };
char int_buffer[digit_count(int_number)];
sprintf(short_buffer, "%d", short_number);
sprintf(int_buffer, "%d", int_number);
}
snprintf
来计算数组大小,我给予+1的支持。然而,值得一提的是,在C99之前似乎没有定义这种行为。从man snprintf
的CONFORMING TO
中可以看到:“SUSv2和C99相互矛盾:当size=0时,SUSv2规定返回一个小于1的未指定返回值,而C99允许在这种情况下str为空,并且像往常一样返回(总是)输出字符串中将要写入的字符数。” - Willsnprintf()
函数。它可以计算需要多少空间。int needed = snprintf(NULL, 0, "%s", value);
if (needed < 1) /* error */;
char *representation = malloc(needed + 1); // add 1 for '\0'
if (!representation) /* error */;
sprintf(representation, "%d", value);
// ... use representation ...
free(representation);
有一种方法可以不使用任何函数来实现,例如这个(可能有点原始,但仍然有效):
char dec_rev[255];
dec_rev[0] = '\0';
int i = 0;
while (val != 0) {
int temp = val % 10;
dec_rev[i] = temp + '0';
//printf("%c\n", dec_rev[i]);
val /= 10;
if (val == 0) {
dec_rev[i + 1] = '\0';
break;
}
i++;
}
char dec[255];
i = 0;
for (int j = strlen(dec_rev) - 1; j != -1; j--) {
dec[i] = dec_rev[j];
i++;
}
最终,我们将我们的整数存储在dec [255]中。
很奇怪这没有被提到,但是一个十进制整数的表示大小是ceil(log10(value)); (或者如果你想要写出它的整数版本,就是log10)
因此 ceil(log10(5)) => 1
并且 ceil(log10(555)) => 3
ceil(log10(1000000000)) => 9
显然,如果需要符号,则需要额外的空间,另一个空间用于'\0'。
asprintf
会是你的好帮手。 - Danaint
是一个32位(有符号或无符号)的量,那么12个字符(10个数字、符号、尾随空值)就足够了。如果它是一个64位有符号量,则需要21个字符(19个数字、符号、尾随空值);对于没有符号的量,21个字符就足够了,但是如果有符号,你需要22个字符。通常的技巧是分配比必要的稍微多一点的空间。你可以使用空字符串和零长度检查snprintf()
的返回值,以找到需要多少空间。你可以看看建议使用的asprintf()
,但它还比较新,可移植性有限。 - Jonathan Leffler