Arrays 尝试将数组字符串作为动态存储的内存返回,但不起作用

Arrays 尝试将数组字符串作为动态存储的内存返回,但不起作用,arrays,c,string,Arrays,C,String,我是C编程新手,目前正在编写一个函数,将字符串复制到字符串数组中,并返回给它的调用者。我已经测试了函数,函数中的一切都很好。(例如:printf函数中的string元素以显示它实际上存储在数组中)但是当我返回string数组时,输出没有显示任何内容 我提到过,但这里的方法似乎对我不起作用 这是我的函数名为 #define ROWS 4 #define WORDS_COUNT 50 char **toStrArray(char str[], char **strArr) { int i

我是C编程新手,目前正在编写一个函数,将字符串复制到字符串数组中,并返回给它的调用者。我已经测试了函数,函数中的一切都很好。(例如:printf函数中的string元素以显示它实际上存储在数组中)但是当我返回string数组时,输出没有显示任何内容

我提到过,但这里的方法似乎对我不起作用

这是我的函数名为

#define ROWS 4
#define WORDS_COUNT 50

char **toStrArray(char str[], char **strArr) 
{
    int i, j, iTmp;
    int len; 
    char *tmp; /* Temporary string to copy each words */

    len = strlen(str);    
    tmp = (char*)malloc(len * sizeof(char));

    j = 0; iTmp = 0;
    /* ASSERTION: Iterate through str and assign the string to strArr */
    for( i = 0; str[i] != '\0'; i++ )
    {
        if( str[i] == ' ' )
        {
            *(strArr + j) = tmp; /* Assign the copied words to strArr */
            /* printf("%s\n", *(strArr + j)); < for testing purposes only */ 
            iTmp = 0; /* Reset back to 0 */
            memset(tmp, 0, len * sizeof(char));
            j++; /* Move to next row */
        }
        else
        {
            tmp[iTmp] = str[i]; /* Copy the words in str to tmp */
            iTmp++;
        }
    }
    *(strArr + j) = tmp; /* Store the last words in the string because the last words is not end with ' ' 
                            but rather '\0' */
    /* printf("%s\n", *(strArr + j)); < for testing purposes only */

    /* Ensures no memory leak */
    free(tmp);
    tmp = NULL;
    return strArr;
}
#定义第4行
#定义单词\u计数50
字符**toStrArray(字符str[],字符**strArr)
{
int i,j,iTmp;
内伦;
char*tmp;/*复制每个单词的临时字符串*/
len=strlen(str);
tmp=(char*)malloc(len*sizeof(char));
j=0;iTmp=0;
/*断言:遍历str并将字符串分配给strArr*/
对于(i=0;str[i]!='\0';i++)
{
如果(str[i]='')
{
*(strArr+j)=tmp;/*将复制的单词分配给strArr*/
/*printf(“%s\n”,*(strArr+j));<仅用于测试*/
iTmp=0;/*重置回0*/
memset(tmp,0,len*sizeof(char));
j++;/*移动到下一行*/
}
其他的
{
tmp[iTmp]=str[i];/*将str中的单词复制到tmp*/
iTmp++;
}
}
*(strArr+j)=tmp;/*存储字符串中的最后一个单词,因为最后一个单词不以“”结尾
而是“\0”*/
/*printf(“%s\n”,*(strArr+j));<仅用于测试目的*/
/*确保没有内存泄漏*/
免费(tmp);
tmp=NULL;
返回斯特拉尔;
}
主叫函数: 输出只是“,”

char str[]=“这茶很好”;
字符**arg_1;
int i;
/*arg_1的字符串数组的分配*/
arg_1=(char**)malloc(ROWS*sizeof(char*));
/*断言:遍历字符串数组的行并分配它们的内存*/
对于(i=0;i<4;i++)
*arg_1=(char*)malloc(WORDS_COUNT*sizeof(char));
arg_1=toStrArray(str,arg_1);
对于(i=0;i<4;i++)
printf(“%s,”,*(arg_1+i));
printf(“\n”);
关于

arg_1 = toStrArray(str, arg_1);
这将覆盖指向以前通过调用
malloc()
分配的动态内存的指针。这将导致无法恢复的内存泄漏。建议:

for( size_t i = 0; i < 4; i++ )
{
    strcpy( argv_1[i], str );
}
但是这里的方法似乎对我不起作用

在该代码中,“字符串数组”声明为

    char sub_str[10][20]; // [1]
您将函数声明为

    char** toStrArray(char str[], char **strArr): // [2]
这些是不同的动物

一般来说,您不会混合使用[]和**符号。您只需声明

   char** toStrArray(char* str, char** strArr); // [3]
返回的值将与
strArr
相同。原因是可以方便地在表达式中使用函数调用。例如,请参见
fgets()

但是
  • 这两个数组本身都不是字符串数组

  • [1] 是一个由10 x 20
    char
    组成的块,从地址
    sub_str

     char sub_str[10][20];
    
只有当10个20字节段中的每一个都以空结尾时,它才是一个字符串数组

  char** strArray;
  • [2] 是指向
    char

      char** strArray;
    
  • *strArray
    是指向
    char

      char** strArray;
    
  • **strArray
    是一个
    字符

      char** strArray;
    
  • 它永远不会是一个字符数组,但它可以是一个指向字符数组的指针数组,这将是最灵活的用法,因为我们可以迭代
    **strArray
    所指向的指针,编写类似
    *strArray[0]
    *srtArray[1]
    等代码。字符串数组

在这两种情况下,必须仔细构造“数组”,否则将不会得到任何数组、字符串、内存泄漏或程序崩溃

我将展示每个案例的一个示例 第一种情况可能有点离题,但我认为比较经常混淆的事情是有道理的

楼宇小组街[10][20] 这里我们只有一个
10*20*sizeof(char)
字节的区域。在C中没有多维数组。每个20字节的段只是从
&sub\u str
开始一个接一个地排列

由于每个字符串都是以null结尾的,我们最多可以有10个字符串,每个字符串的大小可达19字节

#include <stdio.h>
int main(void)
{
    char    sub_str[10][20];

    for (int i = 0; i < 10; i += 1)
        sprintf(
            sub_str[i],
            "%16s%03d",
            "This is string ", i+1
        );

    for (int i = 0; i < 10; i += 1)
        printf(
            "%2d  %s len(%zd)\n",
            i, sub_str[i], strlen(sub_str[i])
        );
    return 0;
};
我们有一个字符串数组。请参见下面的迭代访问第i个字符串

    printf(
    "%2d  %s len(%zd)\n",
    i, sub_str[i], strlen(sub_str[i])
);
这里的问题是,我们几乎没有灵活性,可能浪费了大量内存。所有大小都是固定的,静态的

建筑
char**strArray;
最终 这是最灵活和最熟悉的方法,因为每个C程序都至少使用一个case。
main()
具有通用原型

int main(int argc, char** argv);
在这里,我们看到您的程序中缺少一个非常重要的东西:因为
srtArray
只是一个指针,您需要知道它指向多少个指针。 本身
*strArray
只是一个指向
char
的指针,并且只有在它被分配的情况下。通过声明
char**strArr;
您只会得到一个指针,事实上,它是安全的

        char** strArr = NULL;
考虑一下这一点

typedef struct
{
    int     argc;
    char**  argv;
}   stringArray;
现在收支相抵,事实上你可以宣布

      void toStrArray(char* str, stringArray strArr);
然后将
argc
值打包到
struct

关于程序:代码只是模仿系统对
main()
所做的操作,从命令行参数构建字符串列表,甚至包括作为第一个参数的程序名。然后调用此函数

    int just_like_main(int argc, char** argv)
这会打印出论点

它执行您在功能中必须执行的操作。

请注意,必须有一种方法可以随时控制数组中字符串的数量,就像
argc#define _BLOCK_ 4

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

typedef struct
{
    int     argc;
    char** argv;
}   stringArray;

int just_like_main(int, char**);

int main(void)
{
    const int   n_parm = 16;
    const char* test_strings[16] =
    {
        "Creating", "a", "block", "of",
        "strings", ",", "just", "like",
        "the", "system", "does", "for" ,
        "main()", "for", "every", "program"
    };

    stringArray ex; // example
    int N = _BLOCK_; // 1st block
    ex.argc = 0;
    ex.argv = (char**)malloc(sizeof(char*) * _BLOCK_);
    const char* program_name = "full path of program";
    ex.argv[ex.argc] = (char*)malloc(1 + strlen(program_name));
    strcpy(ex.argv[ex.argc], program_name);
    ex.argc += 1; // 1st arg. That was easy

    // loads all other strings into **argv
    for (int i = 0; i < n_parm; i += 1)
    {   // each one
        if (ex.argc >= N)
        {   // block is full
            N = N + _BLOCK_;
            char* new_block = realloc(ex.argv, (N * sizeof(char*)));
            printf("Block extended for a total of %d pointers\n", N);
            ex.argv = (char**)new_block;
        };
        ex.argv[ex.argc] = (char*)malloc(1 + strlen(test_strings[i]));
        strcpy(ex.argv[ex.argc], test_strings[i]);
        ex.argc += 1;
    };  // for()
    printf("\t%d strings in the block:\n", ex.argc);
    for (int i = 0; i < ex.argc; i += 1)
    {
        printf("\t\t%d of %d: '%s'\n", 1 + i, ex.argc, ex.argv[i]);
    };

    // now trims the end of the block
    // allocated: N.
    // used: argc
    printf("\t%d pointers allocated\n", N);
    printf("\t%d arguments read\n", ex.argc);
    if (N == ex.argc)
        printf("\tNothing to free()\n");
    else
    {
        printf("\t%d pointers to free\n", N - ex.argc);
        char* new_size = realloc(ex.argv, (ex.argc * sizeof(char*)));
        printf("\tBlock size trimmed for a total of %d pointers\n", ex.argc);
        ex.argv = (char**)new_size;
    };
    printf("\tCalling just_like_main() with these args\n");
    int res = just_like_main(ex.argc, ex.argv);
    printf("\n\n\t\"main()\" returned %d\n", res);
    printf("\tNow fres the block and exit\n");
    for (int i = 0; i < ex.argc; i += 1)
        free(ex.argv[i]);
    free(ex.argv);
    printf("\n\nGame over\n");
    return 0;
};

int just_like_main(int argc, char** argv)
{
    printf("\n\tAt \"main()\": %d arguments\n\n", argc);
    for (int i = 0; i < argc; i += 1)
        printf("%8d\t'%s'\n", i, argv[i]);
    return 0;
};  // just_like_main()
Block extended for a total of 8 pointers
Block extended for a total of 12 pointers
Block extended for a total of 16 pointers
Block extended for a total of 20 pointers
        17 strings in the block:
                1 of 17: 'full path of program'
                2 of 17: 'Creating'
                3 of 17: 'a'
                4 of 17: 'block'
                5 of 17: 'of'
                6 of 17: 'strings'
                7 of 17: ','
                8 of 17: 'just'
                9 of 17: 'like'
                10 of 17: 'the'
                11 of 17: 'system'
                12 of 17: 'does'
                13 of 17: 'for'
                14 of 17: 'main()'
                15 of 17: 'for'
                16 of 17: 'every'
                17 of 17: 'program'
        20 pointers allocated
        17 arguments read
        3 pointers to free
        Block size trimmed for a total of 17 pointers
        Calling just_like_main() with these args

        At "main()": 17 arguments

       0        'full path of program'
       1        'Creating'
       2        'a'
       3        'block'
       4        'of'
       5        'strings'
       6        ','
       7        'just'
       8        'like'
       9        'the'
      10        'system'
      11        'does'
      12        'for'
      13        'main()'
      14        'for'
      15        'every'
      16        'program'


        "main()" returned 0
        Now free() the block and exit

Game over
     int just_like_main(int argc, char** argv);