2014-11-21 55 views
0

對於這個Shell程序,我使用函數strtok(見fragmenta.h代碼)來解析用戶引入的字符串。 我需要刪除strotk函數的空白,並介紹指針數組的結構。這是在fragmenta.h中進行的。Shell使用strtok和一個指針數組

在主程序(shell.c)中,需要引入字符串,這個字符串被傳遞給fragmenta並存儲在char ** arg中。之後,我使用execvp函數來執行該命令。

問題是程序存儲整個命令,但只執行第一個單獨的命令。例如,如果我們引入「ls -al」,只執行ls命令,所以我明白這是指針上的問題。

主程序shell.c

#include<string.h> 
#include<stdlib.h> 
#include<stdio.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include "fragmenta.h" 
// 
char cadena[50]; 
int pid; 
int i, status; 
char **arg; 
pid_t pid; 
// 
main() 
{ 
    printf("minishell -> "); 
    printf("Introduce the command \n"); 
    scanf("%[^\n]", cadena); 
    if (strcmp(cadena, "exit") == 0) 
    { 
     exit(0); 
    } 
    else 
    { 
     pid = fork(); 
     if (pid == -1) 
     { 
      printf("Error in fork()\n"); 
      exit(1); 
     } 
     else if (pid == 0) //child proccess 
     { 
      arg = fragmenta(cadena); 
      if (execvp(*arg, arg) < 0)  /* execute the command */ 
      { 
       printf("*** ERROR: exec failed\n"); 
       exit(1); 
      } 
     } 
     else         /* for the parent:  */ 
     { 
      while (wait(&status) != pid); 
     } 
    } 
} 

int len; 
char *dest; 
char *ptr; 
char *aux; 
char **fragmenta(const char *cadena) 
{ 
    // 
    char *token; 
    int i = 0; 
    // 
    len = strlen(cadena); 
    char *cadstr[len + 1]; 
    dest = (char *)malloc((len + 1) * sizeof(char)); 
    strcpy(dest, cadena); 
    //printf("Has introducido:%s\n",dest); 
    token = strtok(dest, " "); 
    while (token != NULL) 
    { 
     cadstr[i] = malloc(strlen(token) + 1); 
     strcpy(cadstr[i], token); 
     token = strtok(NULL, " "); 
     i++; 
    } 
    *cadstr[i] = '\0'; 
    ptr = *cadstr; 
    i = 0; 
    while (cadstr[i] != NULL) 
    { 
     //printf("almacenado: %s\n",cadstr[i]); 
     i++; 
    } 
    return &ptr; 
} 
+0

使用'fgets'而不是'scanf'。 'scanf'是一個PITA使用。 – 2014-11-21 21:51:22

+0

你能不能顯示fragmenta請願書 – 2014-11-21 21:51:51

回答

0

你必須至少有兩個問題。

第一個是這樣的:

ptr=*cadstr; 

你已經通過所有的麻煩去創建一個參數數組,然後你剛纔複製的第一個參數,並返回一個指向該副本。

你可以擺脫ptrreturn cadstr,只是它是一個局部變量,所以只要函數返回,它就可以被覆蓋或釋放。

由於您因爲某種原因將全部內容存儲在Universe中,因此明顯的解決方法是使全局變爲cadstr。 (當然,你不能以這種方式使用C99運行時長度數組,但是如果輸入超過50個字符,你已經編寫了代碼以保證緩衝區溢出,那麼可以安全地將它分配給50個字符串。)

更好的解決方案是在堆上初始化一個新陣列並將其中的所有cadstr複製到它中。或者首先在堆上初始化cadstr


其次,你從來沒有一個NULL追加到的cadstr結束。取而代之的是,你這樣做:

*cadstr[i] = '\0'; 

這使得在cadstr的最後一個元素指向它指向任何未初始化的指針,但修改的第一個字節的無論是成爲0。這可能會破壞重要的內存,或導致段錯誤,或完全無害,但它不能做的一件事是將cadstr[i]設置爲NULL。

當你檢查:

i = 0; 
while (cadstr[i] != NULL) 
    i++; 

...你只能得到的是循環,因爲運氣的;你直接讀取已分配數組的末尾,直到某個其他結構或一些未初始化的內存恰好是連續的sizeof(void*) 0。

當你將同樣的事情傳遞給execvp時,誰知道它會做什麼。


你也宣告main沒有原型,它被廢棄了,所以你可能會從接受了你的代碼的其餘任何編譯器得到一個警告吧。要解決這個問題,只需要做int main()