如何将int
(整数)转换为字符串?
我正在尝试编写一个函数,将struct
的数据转换为字符串以便保存到文件中。
sprintf
来实现,或者如果你有的话,可以使用snprintf
:char str[ENOUGH];
sprintf(str, "%d", 42);
可以使用以下方法计算 str
中字符数(包括终止字符):
(int)((ceil(log10(num))+1)*sizeof(char))
ENOUGH
足够,我们可以通过malloc(sizeof(char)*(int)log10(num))
来实现。 - Hauleth(int)log10(42)
是1
。 - Christian Rau#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
。 - cafint length = snprintf(NULL, 0,"%d",42);
获取长度,然后为字符串分配length+1
个字符,不考虑减号和地区:千位分隔符和分组。 - user2622016正如评论中指出的那样,itoa()
不是标准函数,因此最好使用对手答案中建议的sprintf()方法!
你可以使用itoa()
函数将整数值转换为字符串。
以下是一个示例:
int num = 321;
char snum[5];
// Convert 123 to string [buf]
itoa(num, snum, 10);
// Print our string
printf("%s\n", snum);
如果您想将结构输出到文件中,则无需事先转换任何值。 您可以使用printf格式说明符指示如何输出您的值,并使用来自printf系列 的任何运算符来输出数据。
itoa
函数不是标准函数 - 可以查看例如 https://dev59.com/RHVC5IYBdhLWcg3wxEJ1。 - Paul Rsprintf
或itoa
的情况下获得此内容?可能需要编写自定义标准库来实现。 - S.S. Anne#include <stdlib.h>
。 - Danijel简单回答:
snprintf( str, size, "%d", x );
首先,您需要找到足够的大小。如果您使用NULL, 0
作为第一个参数调用snprintf
,它将告诉您长度:
长一些的是:首先你需要找到足够的大小。snprintf
告诉你长度如果你用 NULL, 0
作为第一个参数:
snprintf( NULL, 0, "%d", x );
为 null 结尾符分配一个额外的字符。
#include <stdio.h>
#include <stdlib.h>
int x = -42;
int length = snprintf( NULL, 0, "%d", x );
char* str = malloc( length + 1 );
snprintf( str, length + 1, "%d", x );
...
free(str);
如果对于每个格式字符串都适用,因此您可以使用"%g"
将浮点数或双精度转换为字符串,您可以使用"%x"
将整数转换为十六进制等。
sprintf
/snprintf
有其优点,但它们只能处理十进制转换中的负数。由于上述链接要么已经下线,要么不再有效,我在下面附上了他们的第四个版本。/**
* C++ version 0.4 char* style "itoa":
* Written by Lukás Chmela
* Released under GPLv3.
*/
char* itoa(int value, char* result, int base) {
// check that the base if valid
if (base < 2 || base > 36) { *result = '\0'; return result; }
char* ptr = result, *ptr1 = result, tmp_char;
int tmp_value;
do {
tmp_value = value;
value /= base;
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
} while ( value );
// Apply negative sign
if (tmp_value < 0) *ptr++ = '-';
*ptr-- = '\0';
// Reverse the string
while(ptr1 < ptr) {
tmp_char = *ptr;
*ptr--= *ptr1;
*ptr1++ = tmp_char;
}
return result;
}
sprintf(str, "%d", 42);
优化为追加两个常量字符,但这只是理论。在实践中,人们不会使用sprintf
来格式化常量整数,而上面的itoa
几乎是最优化的。至少你可以百分之百地确信,你不会得到一个比通用的sprintf
慢数个数量级的结果。如果您有任何反例,请告知使用的编译器版本和设置。 - Eugene Ryabtsevchar str[3]; sprintf(str, "%d", 42);
--> MOV #121A,W4, MOV W4,AF4, MOV #2A,W0 = 2A, MOV #0,W4, CALL 105E
嵌入式编译器简单地将缓冲区和数字42传递给类似于itoa()
的例程。 - chux - Reinstate Monica这里还有另一种方法。
#include <stdio.h>
#define atoa(x) #x
int main(int argc, char *argv[])
{
char *string = atoa(1234567890);
printf("%s\n", string);
return 0;
}
如果您使用的是GCC编译器,您可以使用GNU扩展的asprintf函数。
char* str;
asprintf(&str, "%i", 12313);
free(str);
将任何内容转换为字符串应该是要么1)分配结果字符串,要么2)传入char *
目标和大小。下面是示例代码:
两种方法都适用于所有的int
,包括INT_MIN
。它们提供了一致的输出,而不像snprintf()
那样取决于当前语言环境。
方法1:当内存不足时返回NULL
。
#define INT_DECIMAL_STRING_SIZE(int_type) ((CHAR_BIT*sizeof(int_type)-1)*10/33+3)
char *int_to_string_alloc(int x) {
int i = x;
char buf[INT_DECIMAL_STRING_SIZE(int)];
char *p = &buf[sizeof buf] - 1;
*p = '\0';
if (i >= 0) {
i = -i;
}
do {
p--;
*p = (char) ('0' - i % 10);
i /= 10;
} while (i);
if (x < 0) {
p--;
*p = '-';
}
size_t len = (size_t) (&buf[sizeof buf] - p);
char *s = malloc(len);
if (s) {
memcpy(s, p, len);
}
return s;
}
NULL
。static char *int_to_string_helper(char *dest, size_t n, int x) {
if (n == 0) {
return NULL;
}
if (x <= -10) {
dest = int_to_string_helper(dest, n - 1, x / 10);
if (dest == NULL) return NULL;
}
*dest = (char) ('0' - x % 10);
return dest + 1;
}
char *int_to_string(char *dest, size_t n, int x) {
char *p = dest;
if (n == 0) {
return NULL;
}
n--;
if (x < 0) {
if (n == 0) return NULL;
n--;
*p++ = '-';
} else {
x = -x;
}
p = int_to_string_helper(p, n, x);
if (p == NULL) return NULL;
*p = 0;
return dest;
}
[编辑]根据 @Alter Mann 的要求
(CHAR_BIT*sizeof(int_type)-1)*10/33+3
至少是将某个有符号整数类型编码为由可选负号、数字和空字符组成的字符串所需的最大char
数。
有符号整数中的非符号位不超过CHAR_BIT*sizeof(int_type)-1
。一个n位二进制数的十进制表示最多需要n*log10(2) + 1
位数字。10/33
略大于log10(2)
。+1用于符号char
,+1用于空字符。也可以使用其他分数,如28/93。
方法3:如果想要冒险,并且缓冲区溢出不是问题,则可以使用简单的C99或更高版本解决方案,该方案处理了所有int
。
#include <limits.h>
#include <stdio.h>
static char *itoa_simple_helper(char *dest, int i) {
if (i <= -10) {
dest = itoa_simple_helper(dest, i/10);
}
*dest++ = '0' - i%10;
return dest;
}
char *itoa_simple(char *dest, int i) {
char *s = dest;
if (i < 0) {
*s++ = '-';
} else {
i = -i;
}
*itoa_simple_helper(s, i) = '\0';
return dest;
}
int main() {
char s[100];
puts(itoa_simple(s, 0));
puts(itoa_simple(s, 1));
puts(itoa_simple(s, -1));
puts(itoa_simple(s, 12345));
puts(itoa_simple(s, INT_MAX-1));
puts(itoa_simple(s, INT_MAX));
puts(itoa_simple(s, INT_MIN+1));
puts(itoa_simple(s, INT_MIN));
}
样例输出
0
1
-1
12345
2147483646
2147483647
-2147483647
-2147483648
'0' + x % 10
而不是'0' - x % 10
(将二进制整数映射到十进制0和9之间的二进制ASCII编码)? - étale-cohomologyx%10
的值为[-9 ... 0],当x <= 0
时,不是0到9。 '0' - x % 10
是正确的。使用int
的负面避免了当i == INT_MIN
时i = -i;
的未定义行为,而此代码永远不会出现这种情况。 - chux - Reinstate Monicasprintf 函数返回字节数,并添加一个空字符:
# include <stdio.h>
# include <string.h>
int main() {
char buf[1024];
int n = sprintf( buf, "%d", 2415);
printf("%s %d\n", buf, n);
}
输出:
2415 4
/* Function return size of string and convert signed *
* integer to ascii value and store them in array of *
* character with NULL at the end of the array */
int itoa(int value, char *ptr)
{
int count = 0, temp;
if(ptr == NULL)
return 0;
if(value == 0)
{
*ptr = '0';
return 1;
}
if(value < 0)
{
value* = (-1);
*ptr++ = '-';
count++;
}
for(temp=value; temp>0; temp/=10, ptr++);
*ptr = '\0';
for(temp=value; temp>0; temp/=10)
{
*--ptr = temp%10 + '0';
count++;
}
return count;
}
改进了cnicutar的回答。
包括:
#include <math.h> // log10, floor
#include <stdio.h> // sprintf
#include <stdlib.h> // abs
int num = 123;
计算长度:
size_t len;
if (abs(num)) { // if not zero
len = floor(log10(abs(num)) + 1); // taking 'round' numbers into account too
if (num < 0) len++; // add minus sign
} else { // if zero
len = 1;
}
然后你可以将字符串存储为本地变量:
char str[len];
sprintf(str, "%d", num);
// do stuff
或者作为指针:
char *str = malloc(len * sizeof(char));
sprintf(str, "%d", num);
// do stuff
free(str);
希望这能帮到你!
printf
或其类似函数应该能解决问题。 - pmgint
值的(十进制?)表示。是的,我知道。这是一个非常常见的快捷方式,但它仍然让我感到烦恼。 - dmckee --- ex-moderator kittenitoa
是非标准的,因此snprintf
更具可移植性。 - S.S. Anne