2011-01-31 88 views
1

我弄不清楚我在哪搞乱。我正在传递一组字符指针。在函数内部,我试图使用strtok将一个字符串分解成更小的片段,并将其分配给char *数组。我可以尝试在功能中打印它,并且它都显示正确。只要我尝试将它打印回主内容,我就会得到垃圾。通过引用传递数组

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

#define CMDLEN 100 
#define MAXARG 5 
void prompt(); 
int getCommand (char* cmdAndParameters[]); 

int main() { 
    int numArgs = 0; 
    char* cmdAndParameters [MAXARG]; 

    while (true){ 
      prompt(); 
      numArgs = getCommand (cmdAndParameters); 
    } 
} 

void prompt() { 
    printf("shell> "); 
} 

int getCommand(char* cmdAndParameters[]){ 
    int argNum = 0; 
    bool foundArg = true; 
    char* delimiters = " \t\n"; 
    char userRequest[CMDLEN]; 

    fgets(userRequest,sizeof(userRequest), stdin); 

    if ((cmdAndParameters[argNum] = strtok(userRequest, delimiters)) != NULL) 
    { 
      argNum++; 

      for (; argNum < MAXARG && foundArg; argNum++) { 
       if ((cmdAndParameters[argNum] = strtok(NULL,delimiters)) 
         == NULL) 
       { 
        foundArg = false; 
       } 
       // merely to test output remove later 
       else {printf("%s\n", cmdAndParameters[argNum]);} 
      } 

    } 

    return argNum; 
} 

回答

4

在这种情况下,你的内部字符数组被分配到“自动”,也就是说,在栈上。当你执行strtok时,你将分配一个指向堆栈中分配的内存的指针,然后返回 - 这意味着内存不再分配。

将userRequest数组移动到文件范围(即,在块之外)或将分配设置为“静态”,您将拥有更好的镜头。

更新

嗯,这是比多一点,现在我再看看。

首先,你可以清理相当,如果你使用while循环,像

argNum = 0; 
while((cmdAndParameters[argNum++] = strtok(userRequest, delimiters)) != NULL) 
    ; /* all the work is happening in the conditional part of the while */ 

甚至一个for循环

for(argNum = 0; 
    (cmdAndParameters[argNum] = strtok(userRequest, delimiters)) != NULL); 
    argNum++) 
    ; /* still all the work is in the for */ 

现在如果argNum > 0你知道你发现了什么。

其次,您需要考虑如何以及何时分配内存。您的cmdAndParameters阵列在main开始时(在堆栈中,它是“自动”)分配,因此它与您的程序一样长,您可以在那里使用。但是您的userRequest阵列在getCommand中分配了自动;当getCommand返回时,内存被解除分配;堆栈指针移回来,并且不再有任何保证。所以当你做strtok时,你将指针保存到堆栈中,这可能导致不好的结果。

+1

+1一个非常好的答案。 – 2011-01-31 03:27:30

0

你想

for (; argNum < MAXARG && foundArg; argNum++) 

或类似

for(argCntr = argNum; argCntr < MAXARG && foundArg; argCntr++) 

希望有所帮助。