字符串数组:删除原始数组,然后返回副本

时间:2018-01-28 22:56:50

标签: c arrays

我是C的新手,我正在努力理解分配字符串。

我正在尝试创建一个名为adding_string的函数。它接收零个或多个字符串的数组,在最终位置具有null。接下来,它将数组的浅表副本放大+ 1位置,然后将字符串str的副本附加到数组上。最后,它删除原始数组并返回新副本

这是我到目前为止所做的:

char **adding_string(char **array, const char *str)
{

    size_t num = strlen(str) + 1;
    char *final= (char *)malloc(num);
    strncpy(final, str, num);
    free(array);
    //The above code would create a copy of the string "str".
    //Then it puts that into the array.
    //Not sure if free(array); would be the right method
    //Having issues with returning final too

    return final;
}

main函数中,你会有类似的东西:

char **array = NULL;
char **lines;

array = (char **)calloc(1, sizeof(char *));

array = adding_string(array, "help");
array = adding_string(array, "plz");
array = adding_string(array, "thanks");

for (lines = array; *lines; lines++)
{
    printf("%s\n", *lines);
}

我不确定free(array)是否是用于删除原始数组的正确方法,而且我在返回新副本时遇到问题。

当我尝试返回新副本时,我得到:

warning: return from incompatible pointer type

这是因为:

return final;

2 个答案:

答案 0 :(得分:2)

你的adding_string毫无意义,你复制str,释放记忆 来自array并返回新副本。该函数应该返回一个指向char的双指针, 您正在将单指针传递给char。所有其他价值观都会丢失,你是 像疯了一样泄露记忆。

我会像这样重写你的adding_string

char **adding_string(char **array, const char *str)
{
    char **tmp;
    if(str == NULL)
        return NULL;

    // first make copy
    size_t len = strlen(str);
    char *strcopy = malloc(len+1);
    if(strcopy == NULL)
        return NULL;

    // you've allocated enough memory for the copy
    // no need of strncpy here
    strcpy(strcopy, str);

    // get the number of strings saved
    size_t size = 0; // number of strings saved
    if(array)
    {
        tmp = array;
        while(*(tmp++))
            size++;
    }

    // reallocate memory for array of strings
    tmp = realloc(array, (size+2) * sizeof *tmp);

    if(tmp == NULL)
    {
        // something went wrong, free the copy
        free(strcopy);
        return NULL;
    }

    tmp[size] = strcopy;
    tmp[size+1] = NULL;

    return tmp;
}

请注意,在此版本中,如果arrayNULL,则函数会为此分配内存 字符串数组。这只是一个设计选择,你也可以检查一下 array不是NULL并且传递给adding_string预先分配的数组 字符串。我认为(这只是我的意见)更优雅 adding_string将创建第一个数组。就这样,代码那样 分配内存只在一个地方。

现在在你的主要

char **array = NULL;
char **lines;

// adding_string will allocate the memory for array when it's NULL
array = adding_string(array, "help");
array = adding_string(array, "plz");
array = adding_string(array, "thanks");

for (lines = array; *lines; lines++)
{
    printf("%s\n", *lines);
}

请注意,我

tmp = realloc(array, (size+2) * sizeof *tmp);

size保存了字符串数,这意味着array 保留size+1个空格,因为最后一个指向NULL。你正在追加 还有一个字符串,所以你必须重新分配size+1+1个空格 size+2

请不要忘记随后释放记忆。

答案 1 :(得分:1)

以下程序严格遵循您的需求和意图。

每次添加新字符串时,都会调整数组array的大小。在程序结束时,完成所有已分配内存的正确清理。

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

char ** adding_string(char **array, const char *str)
{
    size_t num = strlen(str) + 1;
    char *final = (char *)malloc(num); // allocate memory for the string `str`
    strncpy(final, str, num);   // create the copy of the `str`  

    int i=0;
    for(i=0; array[i] !=NULL; i++) {}  // find how many elements do we have in the array

    array[i] = final; // add final to the first empty spot in the `array`
    i++;

    char ** new_array = calloc(1+i, sizeof(char *));  // allocate a new array 1 size bigger
    memcpy(new_array, array, sizeof(char*)*i);        // copy all the pointers

    free (array); // no need for the old array 

    return new_array; // return a pointer to the new bigger array
}

int main(void)
{
    char **array = NULL;
    char **lines;

    array = (char **)calloc(1, sizeof(char *)); // allocate array for 4 poiters if type (char *)

    array = adding_string(array, "help");
    array = adding_string(array, "plz");
    array = adding_string(array, "thanks");

    for (lines = array; *lines; lines++)
    {
       printf("%s\n", *lines);
       free(*lines);
    }

    free (array);

    return 0;
}

输出:

help
plz
thanks

这是不同的方法

char *adding_string(const char *str)

将指针(char *)返回给字符串的副本。 array已经预先分配了内存以容纳所有字符串指针。

一个展示这个概念的小程序:

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

char *adding_string(const char *str)
{

    size_t num = strlen(str) + 1;
    char *final= (char *)malloc(num); // allocate memory for the string str
    strncpy(final, str, num);   // crreate the copy 

    return final; // return a pointer to created copy
}


int main(void)
{
    char **array = NULL;

    array = (char **)calloc(4, sizeof(char *)); // allocate array for 4 pointers if type (char *)

    array[0] = adding_string("help");
    array[1] = adding_string("plz");
    array[2] = adding_string("thanks");

    for (int i=0; i<3; i++ )
    {
        printf("%s\n", array[i]);
        free(array[i]);
    }

    free (array);

    return 0;
}

输出:

help
plz
thanks