安全地将int转换为C中的字符串

时间:2014-09-05 17:40:18

标签: c string string-formatting unsigned

根据top answer on SO,我应该怎样做才能将整数转换为C中的字符串:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <math.h>

#define digits(x) ((int)((ceil(log10(abs(x)))+1)*sizeof(char)))

int main () {
    int a = 345908220;
    long b = 23094809284358;
    unsigned int c = 3456789234;
    uint8_t d = 242;
    int64_t e = -840958202029834;

    int dstr_len = digits(a) + digits(b) + digits(c) +
                   digits(d) + digits(e) + 5;

    char dstr[dstr_len];
    sprintf(dstr, "%d %ld %u %u %" PRIu64, a, b, c, d, e);

    printf("%s\n", dstr);

    return 0;
}

然而,这看起来非常低效。我必须将我的程序链接到libmath,并为我要打印的每个整数进行三次数学调用。另请注意,我必须通过计算格式字符串中的空格数,将5添加到我的缓冲区而不仅仅是1 NUL终结符。这似乎也容易出错,并可能导致缓冲区溢出。

那么,有没有什么好的标准函数可以为我计算缓冲区的大小?

我试图写安全的C.

4 个答案:

答案 0 :(得分:5)

如果您的编译器有snprintf()可用,您可以请求格式化的缓冲区长度,然后相应地进行分配:

int dstr_len = snprintf(NULL, 0, "%d %ld %u %u %" PRIu64, a, b, c, d, e) + 1;

char dstr[dstr_len];
//
// NOTE: variable-length arrays are NOT supported in all compilers!
// A more portable solution is:
//
// char *dstr = malloc(sizeof(char) * dstr_len);

snprintf(dstr, dstr_len, "%d %ld %u %u %" PRIu64, a, b, c, d, e);

// free(dstr);

答案 1 :(得分:2)

您可以使用snprintf。从联机帮助页:

  

函数snprintf()和vsnprintf()写入的字节数不超过大小(包括终止空字节(&#39; \ 0&#39;))。如果输出因此限制而被截断,那么返回          value是本来可以使用的字符数(不包括终止空字节)          如果有足够的空间,写入最终字符串。因此,返回值的大小          或更多意味着输出被截断。

因此,您可以使用0调整大小并捕获返回值,然后根据该值进行分配。

答案 2 :(得分:1)

您可以使用asprintf,为您分配足够大的输出字符串。

不要忘记免费输出字符串,因为它是动态分配的。

asprintf适用于Mac OSX,Linux和BSD。如果您希望在其他平台上使用,可以从Apple获得source code

示例:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>

int main () {
    int a = 345908220;
    long b = 23094809284358;
    unsigned int c = 3456789234;
    uint8_t d = 242;
    int64_t e = -840958202029834;

    char *dstr;
    asprintf(&dstr, "%d %ld %u %u %" PRIu64, a, b, c, d, e);
    if (dstr == NULL) {perror(NULL), exit(1);}

    printf("%s\n", dstr);
    free(dstr);

    return 0;
}

答案 3 :(得分:0)

大多数C&#34;运行时环境&#34;最多64位。您可以测试int最多为64位(<stdint.h><limits.h>),然后使用snprintf(不是sprintf,这是不安全的,已弃用)足够大的缓冲区(对于2 64 十进制,32个字节就足够了。)

请参阅limits.h上的Posix规范,其中定义了WORD_BIT所以

#if WORD_BIT > 64
#error cannot compile on this machine
#endif

char buf[32];
snprintf(buf, sizeof(buf), "%d", a);

BTW,<stdint.h>定义several types。您可能需要intmax_t