命令列引數解析函式 —— getopt()
getopt()函式宣告如下:
1 #include <unistd.h> 2 3 int getopt(int argc, char * const argv[], const char *optstring); 4 5 extern char *optarg; 6 extern int optind, opterr, optopt;
該函式的argc和argv引數通常直接從main()的引數直接傳遞而來。optstring是選項字母組成的字串。如果該字串裡的任一字元後面有冒號,那麼這個選項就要求有選項引數。
當給定getopt()命令引數的數量 (
argc
)、指向這些引數的陣列 (argv
) 和選項字串 (optstring
) 後,getopt()
將返回第一個選項,並設定一些全域性變數。使用相同的引數再次呼叫該函式時,它將返回下一個選項,並設定相應的全域性變數。如果不再有可識別的選項,將返回 -1
,此任務就完成了。getopt()
所設定的全域性變數包括:char *optarg
——當前選項引數字串(如果有)。int optind
——argv的當前索引值。當getopt()在while迴圈中使用時,迴圈結束後,剩下的字串視為運算元,在argv[optind]至argv[argc-1]中可以找到。- int opterr——這個變數非零時,getopt()函式為“無效選項”和“缺少引數選項,並輸出其錯誤資訊。
int optopt
——當發現無效選項字元之時,getopt()函式或返回'?'字元,或返回':'字元,並且optopt包含了所發現的無效選項字元。
以下面的程式為例:
選項:
選項:
- -n —— 顯示“我的名字”。
- -g —— 顯示“我女朋友的名字”。
- -l —— 帶引數的選項.
清單2:
1 #include <stdio.h> 2 #include <unistd.h> 3 4 int main (int argc, char **argv) 5 { 6 int oc; /*選項字元 */ 7 char *b_opt_arg; /*選項引數字串 */ 8 9 while((oc = getopt(argc, argv, "ngl:")) != -1) 10 { 11 switch(oc) 12 { 13 case 'n': 14 printf("My name is Lyong.\n"); 15 break; 16 case 'g': 17 printf("Her name is Xxiong.\n"); 18 break; 19 case 'l': 20 b_opt_arg = optarg; 21 printf("Our love is %s\n", optarg); 22 break; 23 } 24 } 25 return 0; 26 }
執行結果:
1 $ ./opt_parse_demo -n 2 My name is Lyong. 3 $ ./opt_parse_demo -g 4 Her name is Xxiong. 5 $ ./opt_parse_demo -l forever 6 Our love is forever 7 $ ./opt_parse_demo -ngl forever 8 My name is Lyong. 9 Her name is Xxiong. 10 Our love is forever
6、改變getopt()對錯誤命令列引數資訊的輸出行為
不正確的呼叫程式在所難免,這種錯誤要麼是命令列選項無效,要麼是缺少選項引數。正常情況下,getopt()會為這兩種情況輸出自己的出錯資訊,並且返回'?'。為了驗證此事,可以修改一下上面的清單2中的程式碼。
清單3:
1 #include <stdio.h> 2 #include <unistd.h> 3 4 int main (int argc, char **argv) 5 { 6 int oc; /*選項字元 */ 7 char *b_opt_arg; /*選項引數字串 */ 8 9 while((oc = getopt(argc, argv, "ngl:")) != -1) 10 { 11 switch(oc) 12 { 13 case 'n': 14 printf("My name is Lyong.\n"); 15 break; 16 case 'g': 17 printf("Her name is Xxiong.\n"); 18 break; 19 case 'l': 20 b_opt_arg = optarg; 21 printf("Our love is %s\n", optarg); 22 break; 23 case '?': 24 printf("arguments error!\n"); 25 break; 26 } 27 } 28 return 0; 29 }
輸入一個錯誤的命令列,結果如下:
1 $ ./opt_parse_demo -l 2 ./opt_parse_demo: option requires an argument -- l 3 arguments error!
如果不希望輸出任何錯誤資訊,或更希望輸出自定義的錯誤資訊。可以採用以下兩種方法來更改getopt()函式的出錯資訊輸出行為:
- 在呼叫getopt()之前,將opterr設定為0,這樣就可以在getopt()函式發現錯誤的時候強制它不輸出任何訊息。
- 如果optstring引數的第一個字元是冒號,那麼getopt()函式就會保持沉默,並根據錯誤情況返回不同字元,如下:
- “無效選項” —— getopt()返回'?',並且optopt包含了無效選項字元(這是正常的行為)。
- “缺少選項引數” —— getopt()返回':',如果optstring的第一個字元不是冒號,那麼getopt()返回'?',這會使得這種情況不能與無效選項的情況區分開。
清單4:
1 #include <stdio.h> 2 #include <unistd.h> 3 4 int main (int argc, char **argv) 5 { 6 int oc; /*選項字元 */ 7 char ec; /*無效的選項字元*/ 8 char *b_opt_arg; /*選項引數字串 */ 9 10 while((oc = getopt(argc, argv, ":ngl:")) != -1) 11 { 12 switch(oc) 13 { 14 case 'n': 15 printf("My name is Lyong.\n"); 16 break; 17 case 'g': 18 printf("Her name is Xxiong.\n"); 19 break; 20 case 'l': 21 b_opt_arg = optarg; 22 printf("Our love is %s\n", optarg); 23 break; 24 case '?': 25 ec = (char)optopt; 26 printf("無效的選項字元 \' %c \'!\n", ec); 27 break; 28 case ':': 29 printf("缺少選項引數!\n"); 30 break; 31 } 32 } 33 return 0; 34 }
測試結果:
$ ./opt_parse_demo -a
無效的選項字元 ' a '!
$ ./opt_parse_demo -l
缺少選項引數!