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

C 字符串数组:删除原始数组,然后返回副本,c,arrays,C,Arrays,我是C语言的新手,我正在努力理解分配字符串 我正在尝试创建一个名为“添加字符串”的函数。它接受一个包含零个或多个字符串的数组,该数组的最终位置为null。接下来,它将使数组的浅层副本增大+1个位置,然后将字符串str的副本附加到数组上。最后,它删除原始数组并返回新的副本 这就是我到目前为止所做的: char **adding_string(char **array, const char *str) { size_t num = strlen(str) + 1; char *f

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

我正在尝试创建一个名为“添加字符串”的函数。它接受一个包含零个或多个字符串的数组,该数组的最终位置为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;

以下计划严格遵循您的需求和意图

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

#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;
}
这是一种不同的方法

char *adding_string(const char *str)
返回指向字符串副本的指针
(char*)
数组
已经预先分配了内存以容纳所有字符串指针

演示该概念的小程序:

#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;
}

您的
添加\u字符串
没有意义,您复制了
str
,释放内存 从
数组
返回新副本。该函数应返回一个指向
char
的双指针, 您正在向
char
传递一个指针。所有其他值都将丢失,您将丢失 疯狂地泄露记忆

我会重写你的
添加字符串
如下:

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;
}
请注意,在此版本中,如果
数组
NULL
,则函数将为 字符串数组。这只是一个设计选择,你也可以检查一下
array
不是
NULL
并传递给
adding\u 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
空格,这是
尺寸+2


请不要忘记以后释放内存。

您不是在复制数组,而是在复制str。final的类型是
char*
,这就是为什么它会显示“不兼容指针类型”-函数应该返回
char**
。@rain city,这很有意义,谢谢。如果我错了,请纠正我,但要解决这个问题,我必须将str更改为array,然后使用strncat将两者相加。接下来,我将返回char**,这将是数组。为什么*行会变为null?@QuasselKasper是一种模拟cstring如何通过使用
'\0'
-终止字节来终止的技术。这里有一个
NULL
指针<
main
中的code>argv
就是这样工作的,最后一个元素是
NULL
。例如,
execv
也要求这样做。非常感谢!这很有道理!
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);