0

我无法按照代码工作。它将用户输入解析为 char*[] 并返回它。但是 char* command[] 不接受任何值并保持填充为 NULL...这里发生了什么?

void* setCommands(int length){         
    char copy[strlen(commandline)];    //commandline is a char* read with gets();
    strcpy(copy, commandline);
    char* commands[length];
    for (int x=0; x<length; x++)
        commands[x] = "\0";
    int i = 0;
    char* temp;
    temp = strtok (copy, " \t");
    while (temp != NULL){
        commands[i] = temp;    //doesnt work here.. commands still filled with NULL afterwards
        i++;
        printf("word:%s\n", temp);
        temp = strtok (NULL, " \t");
    }   
    commands[i] = NULL;
    for (int u=0; u<length; u++)
        printf("%s ", commands[i]);
    printf("\n");
    return *commands;
}

您可能会假设,命令行!= NULL,长度!= 0

4

2 回答 2

0
commands[i] = NULL;
for (int u=0; u<length; u++)
    printf("%s ", commands[i]);

好好看看那个代码。它u用作循环控制变量,但基于i.

因此,由于您已在循环之前的行中设置commands[i]NULL,因此您只会得到一系列 NULL。

commands[u]在循环中使用而不是commands[i].


在此之上:

void* setCommands(int length){         
    char* commands[length];
    :
    return *commands;
}

只会返回一个指针,指向第一个标记的指针,而不是指向标记指针数组的指针。您不能返回超出范围的局部变量的地址(嗯,您可以,但它可能不起作用)。

而且,在任何情况下,由于一个指针最有可能指向另一个局部变量(在内部的某个地方copy),所以它也是无效的。

如果你想从函数中传回内存块,你需要研究 using malloc,在这种情况下,指针数组和字符串本身都是。

于 2013-06-11T02:15:08.937 回答
0

您有许多问题...您的程序当前将表现出未定义的行为,因此在您解决这些问题之前,您无法希望预测正在发生的事情。让我们开始。

以下字符串太短了一个字符。您忘记为字符串终止符 ( '\0') 添加一个字符。这将导致标记化期间缓冲区溢出,这可能是您看到的行为的部分原因。

char copy[strlen(commandline)];   // You need to add 1
strcpy(copy, commandline);

下一部分是您的返回值,但它是一个临时的(本地数组)。您不得退货。你应该分配它。

// Don't do this:
char* commands[length];
for (int x=0; x<length; x++)
    commands[x] = "\0";         // And this is not the right way to zero a pointer

// Do this instead (calloc will zero your elements):
char ** commands = calloc( length, sizeof(char*) );

标记化循环可能会超出您的缓冲区,因为您从不检查length,因此您应该添加一个测试:

while( temp != NULL && i < length )

并且由于上述原因,您不能commands[i]在循环后盲目设置为 NULL 。要么测试,要么i < length不设置它(无论如何你事先将数组归零)。

现在让我们处理返回值。目前你有这个:

return *commands;

这将返回一个指向临时字符串 ( copy) 中第一个标记的指针。首先,看起来您实际上打算返回一个令牌数组,而不仅仅是第一个令牌。其次,您不能返回临时字符串。所以,我认为你的意思是:

return commands;

现在,要处理这些字符串......有一个简单的方法,也是一个聪明的方法。已经提出了一种简单的方法:strdup在将它们推入内存之前调用每个令牌。令人讨厌的部分是,当您清理该内存时,您必须遍历数组并释放每个单独的令牌。

相反,让我们一键完成所有操作,通过一次调用分配数组和字符串存储:

char **commands = malloc( length * sizeof(char*) + strlen(commandline) + 1 );
char *copy = (char*)(commands + length);
strcpy( copy, commandline );

我上面唯一没有做的就是将数组归零。您可以在标记化循环之后执行此操作,只需将剩余值归零即可:

while( i < length ) commands[i++] = NULL;

现在,当您返回时commands,您会返回一个令牌数组,其中还包含自己的令牌存储。要释放数组及其包含的所有字符串,只需执行以下操作:

free( commands );

把它们放在一起:

void* setCommands(int length)
{
    // Create array and string storage in one memory block.
    char **commands = malloc( length * sizeof(char*) + strlen(commandline) + 1 );
    if( commands == NULL ) return NULL;
    char *copy = (char*)(commands + length);
    strcpy( copy, commandline );

    // Tokenise commands
    int i = 0;
    char *temp = strtok(copy, " \t");

    while( temp != NULL && i < length )
    {
        commands[i++] = temp;
        temp = strtok(NULL, " \t");
    }

    // Zero any unused tokens
    while( i < length ) commands[i++] = NULL;

    return commands;
}
于 2013-06-11T02:50:51.053 回答