2015-12-15 28 views
0

我正在編寫一個程序,它從命令行讀取「標誌」以及程序名稱。我希望程序讀取幾個標誌(-i,-c-n),並在調用一個或多個標誌組合時執行不同的功能。對argv []進行迭代會產生段錯誤

這是我開始寫代碼:

printf("Argv 0: %s\n", argv[0]); 
    printf("Argv 1: %s\n", argv[1]); 
    printf("Argv 2: %s\n", argv[2]); 

    for (int i = 1; i <= argc + 1; i++) { 
    if (strcmp("-i", argv[i]) == 0) { 
     printf("%s\n", "found -i"); 
    } 
    else{ 
     printf("%s\n", "did not find -i"); 
    } 

    } 

一個標誌(-i)只是嘗試,但我想它在同一時間讀一個或幾個標誌,並調用相應的功能。

當我執行該程序:

./program-name test -i 
Argv 0: test 
Argv 1: -i 
Argv 2: (null) 
found -i 
Segmentation fault 
+2

不知道定義,是不是'i <= argc + 1'會導致出界限? – MikeCAT

+0

@MikeCAT總之一句話:不,但是'strcmp(「 - i」,argv [argc])'確實如此。 –

回答

1

不要重做經過驗證的舊代碼。浪費時間和重複努力。作爲一個很長時間的C編碼器,我總是(當我記得的時候)在我嘗試從頭開始之前先去看看代碼庫。我首先重新使用然後創建。我很聰明,知道有很多smarterer編碼器在我之前。

使用自由和工作的getopt()和getopt_long()函數爲您解析命令行參數。代碼庫中有很多例子,如果你google搜索「getopt example」but here is the GNU C tutorial

#include <ctype.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

int 
main (int argc, char **argv) 
{ 
    int aflag = 0; 
    int bflag = 0; 
    char *cvalue = NULL; 
    int index; 
    int c; 

    opterr = 0; 

    while ((c = getopt (argc, argv, "abc:")) != -1) 
    switch (c) 
     { 
     case 'a': 
     aflag = 1; 
     break; 
     case 'b': 
     bflag = 1; 
     break; 
     case 'c': 
     cvalue = optarg; 
     break; 
     case '?': 
     if (optopt == 'c') 
      fprintf (stderr, "Option -%c requires an argument.\n", optopt); 
     else if (isprint (optopt)) 
      fprintf (stderr, "Unknown option `-%c'.\n", optopt); 
     else 
      fprintf (stderr, 
        "Unknown option character `\\x%x'.\n", 
        optopt); 
     return 1; 
     default: 
     abort(); 
     } 

    printf ("aflag = %d, bflag = %d, cvalue = %s\n", 
      aflag, bflag, cvalue); 

    for (index = optind; index < argc; index++) 
    printf ("Non-option argument %s\n", argv[index]); 
    return 0; 
} 
+0

謝謝! getopt是要走的路! :d – Wickerman

3

爲了簡化,argc是命令行參數的計數和參數在argv[]保持。作爲C數組有0基於索引,在你的代碼,您需要更改

for (int i = 1; i <= argc + 1; i++) 

for (int i = 1; i < argc; i++) 

限制訪問有效參數列表。

要加一點參考這個,引用C11,章§5.1.2.2.1,程序啓動重點煤礦

如果argc值大於零,由argv[0] 指向的字符串表示程序名稱;如果 程序名稱在主機環境中不可用,則argv[0][0]應爲空字符。如果argc的值是 大於1,則由argv[1]argv[argc-1]指向的字符串 代表程序參數

+0

好嗎?參看我上面的評論。 –

+0

@ PeterA.Schneider從這個角度來看,'argv [argc]'不是_valid_「程序參數」。 (注意_valid_的使用) –

+0

並且從相同的位置進一步引用;-):** argv [argc]應該是一個空指針**雖然不是有效的參數,但是。 –

1

你超出了argv的界限;您的for循環的條件不正確。它應該是i < argc

另外,爲什麼要重新發明輪子?看看getopt()

+0

我不認爲這是正確的。 argv [argc]有效(它的值始終爲空) - 這就是爲什麼* dereferencing *失敗的原因。 –

+0

@ PeterA.Schneider'我 i486

+0

@ i486。 OP的循環是正確的,但是是多餘的。他必須測試argv [i]是否爲null,如果是,則不解除引用(這是argv [argc]的情況。 –

0

與您的代碼和你的循環,這條線是錯誤的:

(strcmp("-i", argv[i]) 

您應該確保的argv [i]是不是NULL,當你把它傳遞到strcmp。該函數已知爲具有NULL指針作爲參數的segfault。你應該更好地測試argv [i]!= NULL,或者在我的循環中放入我< = argc而不是我< = argc + 1,其中包含argv數組字符串中的NULL指針。