2014-11-23 77 views
0

我的代碼應該將一個字符數組解析爲*** char,以便首先按'|'分割它。字符,然後通過空格,換行符等轉換爲單詞。樣品I/O:在將字符串解析成*** char時出現Seg錯誤

I = ls -l | sort | unique 

O =

上述
*cmds[1] = {"ls", "-l", NULL}; 
    *cmds[2] = {"sort", NULL}; 
    *cmds[3] = {"unique", NULL}; 

是指向字符數組,由字,以便分裂,然後在下方是***炭與指針上述指針

char **cmds[] = {1, 2, 3, NULL}; 

現在,我沒有看到我的錯誤(可能是因爲我不熟悉C語言),但程序給出了段錯誤,第二次我從parsePipe()中調用parse(..)函數。任何人都可以幫忙嗎?

void parse(char *line, char **argv) 
{ 
     while (*line != '\0') {  
     while (*line == ' ' || *line == '\t' || *line == '\n') 
      *line++ = '\0'; 
     *argv++ = line;  
     while (*line != '\0' && *line != ' ' && *line != '\t' && *line != '\n'){ 
      line++; 
     } 
    } 
    *argv = '\0'; 
} 

void parsePipe(char *line, char ***cmds) 
{ 
    char *cmd = strtok(line, "|"); 
    int word_counter = 0; 

    while (cmd != NULL) 
    { 
     printf("Printing word -> %s\n", cmd); 
     word_counter++; 
     parse(cmd, *cmds++); 

     cmd = strtok(NULL, "|"); 
    } 

    printf("This string contains %d words separated with |\n",word_counter); 
} 


void main(void) 
{ 
    char line[1024];   
    char **cmds[64]; 
    while (1) {  
     printf("lsh -> "); 
     gets(line);  
     printf("\n"); 
     parsePipe(line, cmds); 
    } 
} 
+2

這是什麼? 'char * 1 [] = {「ls」,「-l」,NULL};'你不能命名一個以數字開頭的變量。 – Almo 2014-11-23 17:08:50

+0

這不是代碼,它是一個示例I/O來展示它應該如何看起來像.. – user3885166 2014-11-23 17:10:34

+0

'argv'按照慣例是'char **'。不要把椅子稱爲桌子。 – alk 2014-11-23 17:13:13

回答

1

[太長評論]

此行

*argv++ = line; /* with char ** argv */ 

指無效存儲器,作爲代碼確實*argv[n](使用char **argv[64]),其是指任何操作。

你使用的命令不會讓生活更輕鬆。

嘗試以下命名:

void parse(char *line, char **cmd) 
{ 
    while (*line != '\0') {  
     while (*line == ' ' || *line == '\t' || *line == '\n') 
      *line++ = '\0'; 
     *cmd++ = line;  
     while (*line != '\0' && *line != ' ' && *line != '\t' && *line != '\n'){ 
      line++; 
     } 
    } 
    *argv = '\0'; 
} 

void parsePipe(char *line, char ***cmdline) 
{ 
    char *cmd = strtok(line, "|"); 
    int word_counter = 0; 

    while (cmd != NULL) 
    { 
     printf("Printing word -> %s\n", cmd); 
     word_counter++; 
     parse(cmd, *cmdline++); 

     cmd = strtok(NULL, "|"); 
    } 

    printf("This string contains %d words separated with |\n",word_counter); 
} 


void main(void) 
{ 
    char line[1024];   
    char **cmdline[64]; 
    while (1) {  
     printf("lsh -> "); 
     gets(line);  
     printf("\n"); 
     parsePipe(line, cmdline); 
    } 
} 

對於沒有cmd小號使用的內存已分配的。

所以

*cmd++ = line; 

失敗,因爲cmd點未成,但被取消引用和代碼試圖寫入到它的指向,這是行不通的,這是無效的內存。


修復這個可以通過傳遞char***parse(char *** pcmd)和計數的令牌來完成發現

size_t nlines = 0; 

... 

++nlines. 

和做

*pcmd = realloc(*pcmd, nlines + 1); /* Allocate one more as needed to later find the end of the array. */ 
(*pcmd)[nlines -1] = line; 
(*pcmd)[nlines] = NULL; /* Initialise the stopper, marking the end of the array. */ 

找到的每個令牌。

顯然,你需要調用它像這樣:

parse(cmd, cmdline++); 

要擁有這一切工作的inital陣列需要正確初始化(你應該無論如何做):

char **cmdline[64] = {0}; 
+0

非常感謝,還有一件事 - 你使用realloc,我們不應該首先malloc變量?如果是這樣,那麼用什麼,nlines = 0? – user3885166 2014-11-23 18:02:58

+0

@ user3885166:做'void * p = NULL; p = realloc(p,42);'和'void * p = malloc(1)一樣。 p = reallc(p,42);'或者甚至是'void * p = realloc(NULL,42);' – alk 2014-11-23 18:04:48

+0

@ user3885166:對於'nlines = 0',你可以跳過'realloc'並且只給'NULL' '* pcmd'或者如果從頭開始已經初始化爲'NULL',則什麼也不做。如果您的編譯器支持,您也可以執行'(* pcmd)= realloc(pcmd,0);'但要注意,對於後一種情況,您需要調用'free(* pcmd)'。如果你定義了一個空的「* command *」,用'* pcmd = NULL'來表示,那就沒有必要了。 – alk 2014-11-23 18:09:14