代码之家  ›  专栏  ›  技术社区  ›  SlappyTheFish

为char数组分配内存以连接已知的文本和整数

  •  2
  • SlappyTheFish  · 技术社区  · 16 年前

    我想连接一段文本,例如“答案是”和一个带符号的整数,以给出输出“数字是42”。

    我知道这段文字有多长(14个字符),但我不知道数字的字符串表示形式会有多少个字符。

    我假设在最坏的情况下,最大的有符号16位整数有5位,加上一个额外的,以防它是负数,那么下面的代码是正确的方法吗?

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        char *message;
    
        message = malloc(14*sizeof(char)+(sizeof(int)*5)+1);
    
        sprintf(message, "The answer is %d", 42);
    
        puts(message);
    
        free(message);
    }
    
    6 回复  |  直到 14 年前
        1
  •  7
  •   codaddict    16 年前

    用途:

    malloc(14*sizeof(char) /*for the 14 char text*/
           +(sizeof(char)*5) /*for the magnitude of the max number*/
           +1 /* for the sign of the number*/
           +1 /* for NULL char*/
          );
    

    因为数字会被表示出来 作为char,必须使用sizeof(char) 而不是sizeof(int)。

        2
  •  3
  •   paxdiablo    16 年前

    不完全是,你只需要几个字符,所以 sizeof(int) 不是必需的。

    但是,对于易于维护和可移植的代码,您应该具有如下特性:

    #define TEXT "The answer is "
    #undef CHARS_PER_INT
    #if INT_MAX == 32767
        #define CHARS_PER_INT 6
    #endif
    #if INT_MAX == 2147483647
        #define CHARS_PER_INT 11
    #endif
    #ifndef CHARS_PER_INT
        #error Suspect system, I have no idea how many chars to allocate for an int.
    #endif
    
    int main (void) {
        char *message;
    
        message = malloc(sizeof(TEXT)+CHARS_PER_INT+1);
        sprintf(message, TEXT "%d", 42);
        puts(message);
        free(message);
        return 0;
    }
    

    这有许多优点:

    • 如果你改变字符串,你只改变一件事一件事。论点 malloc 自动调整。
    • 表达式 sizeof(TEXT)+CHARS_PER_INT+1 在编译时计算。一个涉及 strlen 会有运行时成本。
    • 如果你试图在一个整数可能导致溢出的系统上编译你的代码,你会被告知它(去修正代码)。
    • 实际上应该为数字分配一个额外的字符,因为最大的16位数字(以字符数计)是 -32768 (六个字符长)。你会注意到我 仍然 有一个 +1 最后-这是因为您需要为字符串空终止符留出空间。
        3
  •  1
  •   JXG Jasmynn Flores    16 年前

    一种方法(不一定推荐)是使用 stdio 功能本身。

    例如,如果在分配内存之前打印数字(无论出于什么原因),则可以使用 %n 标识符格式 printf . %N 不打印任何内容;而是提供一个指向 int 普林特 填充到目前为止已写入的字符数。

    另一个例子是 snprintf ,如果你有。您将希望它写入字符串的最大字符数传递给它,它将返回它的字符数。 应该 已经写好了,不算最后的nul。(或错误时为-1。)因此,使用1字节的虚拟字符串, SNPrTNF 可以准确地告诉你你的号码是多少个字符。

    使用这些函数的一个最大优点是,如果您决定更改数字的格式(前导0、填充空格、八进制输出、长整型等),您将不会超出内存。

    如果您的GNU扩展到 STDIO ,您可以考虑使用 asprintf .这就像 sprintf ,除非它为您分配内存!不需要程序集。(尽管你需要自己把它释放出来)但你不应该依赖它来携带。

        4
  •  0
  •   Oddthinking    16 年前

    malloc((14 + 6 + 1) * sizeof(char));

    • 字符串为14个字符
    • 6表示数字+符号
    • 1的“0”

    注意:size of(int)给出了byes中类型的大小。sizeof(int)==4如果int是32位,8如果是64位。

        5
  •  0
  •   Matteo Italia    16 年前

    我认为获得整数的十进制表示的最大长度的正确公式是(floor(log10(int_max))+1);您也可以这样滥用预处理器:

    #include <limits.h>
    #define TOSTRING_(x) #x
    #define TOSTRING(x) TOSTRING_(x)
    /* ... */
    #define YOUR_MESSAGE "The answer is "
    char message[]=YOUR_MESSAGE "+" TOSTRING(INT_MAX);
    sprintf(message+sizeof(YOUR_MESSAGE),"%d", 42);
    

    ,这也避免了堆分配。您可能希望使用snprintf来获得更好的安全性,尽管使用这种方法不必这样做。

    另一个类似的技巧是创建这样的函数:

    size_t GetIntMaxLenght()
    {
        const char dummy[]=TOSTRING(INT_MAX);
        return sizeof(dummy)+1;
    }
    

    如果编译器足够聪明,它可以完全清除 笨蛋 来自已编译代码的var,否则最好声明var为静态变量,以避免每次调用函数时重新初始化它。

        6
  •  0
  •   caf    14 年前

    有符号的安全近似 int 是(包括电位在内的位数) - 符号):

    (CHAR_BIT * sizeof(int) + 1) / 3 + 1
    

    相当于 unsigned 是:

    (CHAR_BIT * sizeof(unsigned) + 2) / 3
    

    这将计算位数-如果为以空结尾的字符串分配空间,则在两个数字中都添加一个以说明终止符。

    本遗嘱 轻微地 高估非常长类型所需的空间(在不寻常的情况下也会高估 int 有填充位),但它是一个很好的近似值,并且具有编译时常量的优点。 CHAR_BIT 是由 <limits.h> .

    推荐文章