【问题标题】:How to add null terminator to char pointer, when using strcpy使用 strcpy 时如何将空终止符添加到 char 指针
【发布时间】:2015-04-24 22:05:45
【问题描述】:

我有一个程序正在尝试使用strcpy() 函数。我知道当使用 char 数组时,例如:char array[10] 可以通过以下方式设置空终止符:array[0] = '\0'; 但是,在使用 char 指针时我将如何设置空终止符?

编辑:程序编译,但输出垃圾

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    char *target;
    char *src = "Test";

    target = malloc(sizeof(char));
    src = malloc(sizeof(char));

     strcpy(target,src);
     printf("%c\n",target); 

    return 0;
}

【问题讨论】:

    标签: c pointers char malloc strcpy


    【解决方案1】:

    你不需要。 strcpy() 的第二个参数需要以 nul 终止,第一个参数需要适合源中的字符数 + nul 终止符。

    您的代码中的问题是:

    1. 您以错误的方式使用sizeof 运算符,并且通过再次分配内存来覆盖src 指针。

      要获取字符串的长度,您需要strlen(),而无需在每个指针上调用malloc()

      因为src 指向新分配的空间,所以您正在从未初始化的数据复制,因为

      src = malloc(sizeof(char));
      

      你不应该那样做。

    2. sizeof(char) == 1 根据定义,因此您只为 1 个字节分配空间,如果它是有效的 C 字符串,则必须为 '\0',因为只有 1 个字符的空间。

    3. 字符串的正确printf() 说明符是"%s",您使用的是用于字符的"%c"

    正确的做法是

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int main(void)
    {
        char       *target;
        const char *src;
    
        src    = "Test"; /* point to a static string literal */
        target = malloc(1 + strlen(src)); /* allocate space for the copy of the string */
        if (target == NULL) /* check that nothing special happened to prevent tragedy  */
            return -1;
    
        strcpy(target, src);
        printf("%s\n", target);
        /* don't forget to free the malloced pointer */
        free(target);
    
        return 0;
    }
    

    【讨论】:

    • 但是我得到了垃圾作为输出。
    • 仍然在我的编译器上提供垃圾作为输出。此外,在 ideone 上,输出为空:ideone.com/duBdgX
    • 没关系,你刚刚又编辑了一遍。感谢您的洞察力!
    • @user20842454566 是的,ideone 处的代码有错误的printf() 说明符。
    【解决方案2】:

    在您的代码中

    strcpy(target,src);
    

    src 不是以空值结尾的。这会调用未定义的行为。

    另外,通过使用malloc(sizeof(char));,您只为单个char 元素分配内存。这可能是你不想要的。

    接下来,根据strcpy()man page,(强调我的)

    strcpy() 函数将src 指向的字符串,包括终止空字节('\0')复制到dest 指向的缓冲区。字符串不能重叠,目标字符串dest 必须足够大以接收副本

    所以,只要

    1. 您的源是正确的以空字符结尾的字符数组 (string)
    2. destination 有足够的内存来保存 source 的内容

    你可以走了。所以,你必须

    1. 空终止src 数组。
    2. target分配足够的内存,以便它可以容纳src的包含。

    最后,提一下,一旦你使用了一个字符串,你应该使用%s 格式说明符和printf() 来打印字符串。

    【讨论】:

      【解决方案3】:
      man strcpy
      

      描述
      strcpy() 函数将 src 指向的字符串,包括终止的空字节 ('\0') 复制到 dest 指向的缓冲区中。

      因此,如果 src 已经有空终止字节,则不必添加它。

      错误
      如果 strcpy() 的目标字符串不够大,那么任何事情都可能发生。

      所以:

      char *src = "Test"; //  4 chars + '\0'
      target = malloc(sizeof(char)); // Space for 1 char
       strcpy(target,src); // Woops !
      

      【讨论】:

        【解决方案4】:
        target = malloc(10);
        

        具有容纳字符串和 nul 终止符的内存。我不明白您为什么要为 src 分配内存,因为我看到您使用的是字符串文字。只需为目标分配足够的内存并执行strcpy() 确保您没有写入超出范围的数组。

        正确的方法是

        target = malloc((strlen(src) + 1));
        

        做的时候记下

        char *src = "Test";
        

        字符串"Test" 存储在只读位置,该位置的地址返回给src。因此,您的字符串已经在内存中,无需再次为此分配内存,而您正在尝试执行并错误地执行此操作。所以去掉malloc() 换成src

        【讨论】:

          【解决方案5】:

          到目前为止,答案已经解决了您的代码中的缺陷和明显的误解,而不是您的问题。指向内存的指针可以像数组一样被索引,所以给出:

          char *target = malloc( 10 ) ;
          

          可以这样设置元素:

          target[0] = '\0' ;
          

          【讨论】:

            【解决方案6】:

            Sourav Ghosh 的回答是正确的,但对于这种特定情况,您应该使用 strdup(),因为它会为您处理内存分配和复制:

            #include <stdio.h>
            #include <string.h>
            #include <stdlib.h>
            
            int main(void)
            {
                const char *src = "Test";   // You should make this const
                char *target = strdup(src); // Duplicate             
                if (target == NULL) {       // Check
                    return EXIT_FAILURE;
                }
                printf("%s\n", target);
                return EXIT_SUCCESS;
            }   
            

            【讨论】:

              猜你喜欢
              • 2017-04-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-08-11
              • 1970-01-01
              • 1970-01-01
              • 2011-12-05
              • 1970-01-01
              相关资源
              最近更新 更多