【问题标题】:Array of char* in CC中的char *数组
【发布时间】:2012-01-23 02:21:42
【问题描述】:

我希望我的程序做的是从用户读取输入文本,将该字符串标记为空格作为分隔符,并将每个标记存储在一个 char* 数组中,然后将其返回。

这是我试图使其正常工作的代码的 sn-p:

typedef char* String;
String* split(char* cmd)
{
    char* param;
    char tmp[128];
    String* result = (String*) malloc(10*sizeof(String));
    memset(result,NULL,10);

    strcpy(tmp,cmd);

    param = strtok(tmp," ");

    int index = 0;
    while(param && index < sizeof(result) / sizeof(*result))
    {

        result[index] = (char*) malloc(strlen(param));
        strcpy(result[index],param);

        param = strtok(NULL," ");
        index++;
    }

}

其中 cmd 是我要标记的字符串,result 是包含每个标记的数组。

当尝试使用简单的 for 循环遍历返回的结果时,此 sn-p 会导致错误(出现分段错误)

String* splittedCmd = split(command);

int i;
for(i=0;i<10;i++)
{
    if(splittedCmd[i] != NULL)
        printf("%s\n",splittedCmd[i]);
}

【问题讨论】:

  • 考虑局部变量和生命周期。想想动态分配,以及为什么你没有它。考虑改用strncpy。考虑将其标记为“家庭作业”。并考虑切换到 C++。

标签: c arrays char


【解决方案1】:

这里有几个问题。

首先,也是最明显的,您将返回result,它是一个数组(但衰减为指向数组的指针),它在函数的堆栈上分配,因此在函数返回时会被回收。你需要动态分配数组(并依赖调用者free它):

String *result = malloc(10 * sizeof(String));

另外,停止while 循环的条件:

if(index == sizeof(result))

将让循环一直进行到index40(如果char* 在您的平台上为4 个字节),因为sizeof 返回操作数的大小(以字节为单位,而不是数组元素),所以sizeof(result) 是(同样,取决于平台) 40. 这显然超出了数组的范围。

如果您仍在使用本地数组而不是 malloc,则可以将其更改为

if (index == sizeof(result) / sizeof(*result))

但是,您现在不能这样做,因为result 只是一个指针而不是一个数组,而sizeof(result) 将始终是您平台上指针的大小。

您可以完全删除 if 并将 while 条件更改为

while (param && index < 10)

这确保param 不是NULL 并且index 小于10。您应该考虑制作#defineconst int 或其他适合数组大小的东西并使用它而不是使用幻数。

你也需要改变

memset(result,NULL,10);

memset(result,NULL, sizeof(String) * 10);

因为如果你不这样做,memset 只会将指向result 的内存的前 10 个字节设置为 0,而不是整个设置,因为它以字节为单位,而不是数组元素。

【讨论】:

  • 我尝试分配内存,还是无法打印splittedCmd的内容
  • @user1162954 发布您更新的代码。不要忘记你也必须改变你的循环。
  • @user1162954 是的,你做了我之前写过的while(param &amp;&amp; index &lt; sizeof(result) / sizeof(*result)),但我犯了一个错误,这也是错误的。阅读我的更新答案(tl;dr:循环应该是while (result &amp;&amp; index &lt; 10),因为sizeof 在指针上的工作方式与在数组上的工作方式不同)。
  • 我明白了,但是即使参数有一个令牌,程序也会崩溃
  • @user1162954 我还看到您现在在您的程序中删除了return result;。您需要重新添加它。
【解决方案2】:

只是一个提示 - 你为什么不尝试使用strtok?这将大大简化事情。

【讨论】:

  • 我猜其他人也没有意识到他已经在使用它了 :)
  • 是的,在堆栈上分配的结果很好。我正要编辑我的答案,说当你的答案出现时。
【解决方案3】:

您不应返回指向局部变量的指针。函数split返回后,result的内存地址可能包含垃圾,所以打印时引用了无效指针。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-14
    • 2021-12-14
    • 2019-07-30
    • 1970-01-01
    • 2012-04-15
    相关资源
    最近更新 更多