【问题标题】:Copying a string into a dynamical two-dimensional array将字符串复制到动态二维数组中
【发布时间】:2014-12-29 15:30:40
【问题描述】:

就像标题已经说明的那样,我想将各种字符串复制到二维数组中。每个字符串都有不同的大小,因此我需要使用内存重新分配。下面的代码应该可以完成这项工作,但不知何故我无法让它工作。

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

int main(void) {

char **str = NULL;
int str_num = 1;

// get string
char *str_new = "hey mate\0";

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

// reallocation for str_new
str = realloc(str,str_num*sizeof(char));
str[str_num-1] = realloc(str,strlen(str_new));

// copy string to new space
strcpy(*str, str_new);

// displaying string
printf("%s\n",str[str_num-1]);


return EXIT_SUCCESS;

}

【问题讨论】:

  • 两件事:编译器自动将字符串终止符'\0'添加到所有字符串文字中,并且所有字符串文字都是只读的,因此指向它们的指针应该是const。

标签: c arrays memory dynamic


【解决方案1】:

一个问题在于重新分配:

str = realloc(str,str_num*sizeof(char));

您只能为单个字节分配空间,而不是为指向char 的指针分配空间。这导致undefined behavior。

改为例如

str = realloc(str,str_num*sizeof(char*));

另一个问题,也是未定义行为的一个原因是实际的字符串分配:

str[str_num-1] = realloc(str,strlen(str_new));

你在这里重新分配 str 而不是 str[0]。 而且你没有为字符串终止符分配空间。

为此,根本不要使用realloc,因为你只需要一次分配它,你只需要malloc,或者只需使用strdup函数在一次调用中进行分配和复制:

str[str_num - 1] = strdup(str_new);

顺便说一句,当使用realloc 时,永远不要分配给你作为第一个参数传入的同一个指针,因为如果realloc 函数失败,它将返回NULL,你将失去原来的指针。而是分配给一个临时指针,如果它是非空的,则分配给实际的指针。

【讨论】:

  • 是否可以在使用 malloc 或 calloc 分配字符串之前对字符串使用 realloc()?
  • @ryyker 可以在 NULL 指针上使用 realloc。 (类似于malloc)。
  • @ryyker 将NULL 指针传递给realloc 相当于做malloc。
  • str = realloc(str, newsize) 可能会导致内存泄漏。
【解决方案2】:
char **str = malloc(sizeof(char *) * n); /* n= number of pointers */

先为指针分配内存,然后再为单个指针分配内存

   for(i=0;i<n;i++)
   {
       str[i] = malloc(sizeof(char) * 20);
       /* copy your string to the allocated memory location here*/
   }

否则你可以拥有

char **str = NULL;

str = realloc(str,str_num * sizeof(char *));

【讨论】:

    【解决方案3】:

    我觉得你没看懂realloc是做什么的,你贴的代码不对,那代码应该这样写

    char **str = NULL;
    int str_num = 1;
    
    // get string
    char *str_new = "hey mate\0";
    
    printf("%s\n",str_new);
    
    /*
        // reallocation for str_new
        str = realloc(str, str_num * sizeof(char));
     */ 
    /* allocate space for `str_num` pointers of char */
    str = malloc(str_num * sizeof(char *));
    if (str == NULL) /* check it worked */
        return -1;
    
    /* allocate space for the number of characters in str_new and
     * the termination null byte 
     */
    str[str_num - 1] = malloc(1 + strlen(str_new));
    if (str[str_num - 1] == NULL)
    {
        free(str);
        return -1;
    }
    /*
     * // copy string to new space
     * strcpy(*str, str_new);
     */
    /* use the same index since if str_num > 1 the above is wrong */
    strcpy(str[str_num - 1], str_new);
    
    // displaying string
    printf("%s\n",str[str_num - 1]);
    

    realloc应该这样使用

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void) 
    {
        char **str = NULL;
        int str_num;
        // get string
        char *str_new[2] = {"hey mate 1", "hey mate 2"};
    
        for (str_num = 0 ; str_num < 2 ; ++str_num)
        {
            char **pointer;
            printf("%s\n", str_new[str_num]);
            /*
                // reallocation for str_new
                str = realloc(str, str_num * sizeof(char));
             */ 
    
            /* re-allocate space for `str_num` pointers of char */
            pointer = realloc(str, (1 + str_num) * sizeof(char *));
            /* 
             * If you use
             * 
             *      str = realloc(str, str_num * sizeof(char *));
             * 
             * you wont be able to free(str) on failure
             */
            if (pointer == NULL)
            {
                int j;
                /* on failure cleanup and return */
                for (j = str_num - 1 ; j >= 0 ; --j)
                    free(str[j]);
                free(str);
    
                return -1;
            }
            str = pointer;      
    
            /* allocate space for the number of characters in str_new and
             * the termination null byte 
             */
            str[str_num] = malloc(1 + strlen(str_new[str_num]));
            if (str[str_num] == NULL)
            {
                free(str);
                return -1;
            }
            /*
             * // copy string to new space
             * strcpy(*str, str_new);
             */
            /* use the same index since if str_num > 1 the above is wrong */
            strcpy(str[str_num], str_new[str_num]);
    
            // displaying string
            printf("%s\n",str[str_num]);
        }
    
        return EXIT_SUCCESS;
    }
    

    你应该记得free所有分配的内存。

    您也不需要将'\0' 嵌入字符串文字中。

    【讨论】:

      【解决方案4】:

      除了更正(如Joachim Pileborg's answer 中指出的那样)

      str = realloc(str,str_num*sizeof(char));  
      

      到

      str = realloc(str,str_num*sizeof(*str));
      

      您应该注意,传递给realloc 的指针必须是任何malloc 系列函数返回的指针,否则它指向NULL。你可以这样做

      str[str_num-1] = NULL;
      str[str_num-1] = realloc(str[str_num-1], strlen(str_new)+1);
      

      【讨论】:

      • @WhozCraig,您可能在建议的更正中错过了*。这两个语句是相同的。
      • @B.Shankar strlen(str_new) 和 strlen(str_new)+1 是完全一样的。我认为您的意思是破解原始帖子,是的,缺少*。已添加。
      猜你喜欢
      • 1970-01-01
      • 2018-05-17
      • 1970-01-01
      • 1970-01-01
      • 2021-07-02
      • 2019-06-10
      • 1970-01-01
      • 2020-07-03
      • 2022-06-16
      相关资源
      最近更新 更多