我在跟踪Code工作时遇到了问题。它将用户输入解析为char * []并返回它。但是char *命令[]不接受任何值并且保持填充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
答案 0 :(得分: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
内的某个地方),它也无效。
如果你想从函数中传回内存块,你需要考虑使用malloc
,在这种情况下,对于指针数组和字符串本身都是如此。
答案 1 :(得分: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;
}