2011-01-31 78 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++) 

希望有所幫助。