getopt函數

getopt -- 解析命令的可選項
 
【說明】getopt只是一個簡單的解析命令可選項的函數,只能進行簡單的格式命令解析,格式如下:
 
1、形如:cmd [-a][-b] //對短選項的解析;
2、形如:cmd [-a a_argument][-b b_argument] //對短選項及短選項的參數解析;
3、形如:cmd [-a[a_argument]] //選項a的參數也是可選的情況解析
 
原型:
 
#include <unistd.h>
 
extern char *optarg;
extern int optind, opterr, optopt;
int getopt(int argc, char * const argv[], const char *optstring);
 
描述:
 
1、getopt函數解析命令行參數,argcargv是調用main函數時傳入的參數。傳入的'-'開始的字符被解析爲選項,getopt一次執行解析出一個option,如果循環執行,可以將argv中的全部option解析出來;
2、在getopt的執行中,每次進入都會更新optind變量,該變量指向下一個argv參數;
3、如getopt返回-1,表示argv[]中的所有選項被解析出,optind指向第一個非選項的argument元素;這裏要注意,在getopt執行過程中會將單獨的argument交換到argv數組的後面,option選項提前,如:cmd -a file1 -b file2,如果a/b均爲不帶參數的選項,這最終argv數組變爲:cmd -a -b file1 file2;
4、optstring指定選項合法的選項,一個字符代表一個選項,在字符後面加一個':'表示該選項帶一個參數,字符後帶兩個':'表示該選項帶可選參數(參數可有可無),若有參數,optarg指向該該參數,否則optarg爲0;
5、前面說了getopt會進行argv順序的調整,但也可以通過設置optstring改變它的方式,這裏有兩種:
     1) 如果optstring的第一個參數是'+'或者POSIXLY_CORRECT被設置,則getopt在原argv的順序上遇到第一個非選項就返回-1;
     2) 如果optstring的第一個參數是'-',則會將所有的非選項當選項處理,並且返回1,用字符代碼1表示該選項;
6、如果getopt不能識別一個選項字符,它會打印一個錯誤消息到stderr上,並將該字符存放到optopt中,返回'?';調用程序可以設置opterr=0設置不打印錯誤信息;注意:要使能打印錯誤信息,optstring的第一個字符(或者在第一個字符是+/-之後)不能是':',否則也不會打印錯誤;
7、如果optstring中指定了option需要參數,但在命令行沒有參數,那麼getopt將返回'?',如果在optstring的第一個字符(或者在第一個字符是+/-之後)是':',那麼將返回':';
 
返回值:
 
1、返回類型爲int,這個在編程的時候要注意,因爲返回值類型範圍要包含-1,很容易返回值接收定義爲char,但在一些系統中char是無符號的,將導致程序錯誤;
2、當傳入的argv中的選項全部被解析,getopt()返回-1,這也是getopt進行選項解析的循環截至條件;
3、如果argv中解析出optstring中描述的選項字符,則返回該字符,如果該選項指定了參數,則全局變量optarg指向該參數;
4、如果getopt遇到一個非optstring指定的選項字符,這表示該選項是未識別的,返回'?',並且將該選項存放到全局變量optopt中;
5、如果optstring指定了選項必須帶參數,但傳入的相應option丟失了參數,返回值依賴於optstring的第一個字符,若第一個字符是':',返回':',否則返回'?';由於非法的選項返回也是'?',所以常常optstring的第一個字符指定爲':';同時將該選項存放到全局變量 optopt中;
 
測試例程:
 
複製代碼
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <string.h>
 5 #include <sys/types.h>
 6  
 7 int main(int argc, char *argv[])
 8 {   
 9         extern char *optarg;
10         extern int optind, opterr, optopt;
11         int i;
12         int ret;
13  
14         for (i=0; i<argc; i++)
15         {   
16                 printf ("argv[%d] %s\n", i, argv[i]);
17         }   
18         printf ("\n");
19  
20         while ((ret = getopt(argc, argv, ":a:b::c")) != -1)
21         {   
22                 switch (ret) {
23                 case 'a':
24                         printf ("option: %c argv: %s\n", ret, optarg);
25                         break;
26                 case 'b':
27                         if (optarg)
28                                 printf ("option: %c argv: %s\n", ret, optarg);
29                         else
30                                 printf ("option: %c no argument\n", ret);
31                         break;
32                 case '?':
33                         printf ("encountered a unrecognized option: %c, argv: %s\n", optopt, argv[optind - 1]);
34                         break;
35                 case ':':
36                         printf ("option: %c missing argument\n", optopt);
37                         break;
38                 default:
39                         printf ("option: %c\n", ret);
40                         break;
41                 }   
42         }
43  
44         printf ("\noptind: %d\n\n", optind);
45         for (i=optind; i>0 && i<argc; i++)
46                 printf ("argv[%d] %s\n", i, argv[i]);
47  
48         printf ("\n");
49         for (i=0; i<argc; i++)
50                 printf ("argv[%d] %s\n", i, argv[i]);
51  
52         return 0;
53 }
複製代碼
然後我們運行測試例程,自己根據前面的描述進行一些分析:
 
root@ParseCmdLine:./parse_cmdline -axxx -byyy
argv[0] ./parse_cmdline
argv[1] -axxx
argv[2] -byyy
 
option: a argv: xxx
option: b argv: yyy
 
optind: 3
 
 
argv[0] ./parse_cmdline
argv[1] -axxx
argv[2] -byyy
 
root@ParseCmdLine:./parse_cmdline -a xxx -b yyy
argv[0] ./parse_cmdline
argv[1] -a
argv[2] xxx
argv[3] -b
argv[4] yyy
 
option: a argv: xxx
option: b no argument
 
optind: 4
 
argv[4] yyy
 
argv[0] ./parse_cmdline
argv[1] -a
argv[2] xxx
argv[3] -b
argv[4] yyy
從這個可以看出,帶參數的option參數可以緊跟,也可以中間有空格;
 
root@ParseCmdLine:./parse_cmdline -axxx -b yyy -c
argv[0] ./parse_cmdline
argv[1] -axxx
argv[2] -b
argv[3] yyy
argv[4] -c
 
option: a argv: xxx
option: b no argument
option: c
 
optind: 4
 
argv[4] yyy
 
argv[0] ./parse_cmdline
argv[1] -axxx
argv[2] -b
argv[3] -c
argv[4] yyy
 
root@ParseCmdLine:./parse_cmdline -axxx -byyy -c
argv[0] ./parse_cmdline
argv[1] -axxx
argv[2] -byyy
argv[3] -c
 
option: a argv: xxx
option: b argv: yyy
option: c
 
optind: 4
 
 
argv[0] ./parse_cmdline
argv[1] -axxx
argv[2] -byyy
argv[3] -c
從這裏可以看出,對於-b是可跟參數也可不跟參數的,參數必須緊跟,中間不能有空格。同時還可以看出:在有argument在argv中,最後出現了argv[]元素位置變化,選項前移了,而參數後移
 
root@ParseCmdLine:./parse_cmdline -x
argv[0] ./parse_cmdline
argv[1] -x
 
encountered a unrecognized option: x, argv: -x
 
optind: 2
 
 
argv[0] ./parse_cmdline
argv[1] -x
 
root@ParseCmdLine:./parse_cmdline -a
argv[0] ./parse_cmdline
argv[1] -a
 
option: a missing argument
 
optind: 2
 
 
argv[0] ./parse_cmdline
argv[1] -a
這裏可以看出未識別的option,和丟失參數的option情況;
 
// 修改代碼while ((ret = getopt(argc, argv, "a:b::c")) != -1)
root@ParseCmdLine:./parse_cmdline -x                   
argv[0] ./parse_cmdline
argv[1] -x
 
./parse_cmdline: invalid option -- x
encountered a unrecognized option: x, argv: -x
 
optind: 2
 
 
argv[0] ./parse_cmdline
argv[1] -x
 
// 修改代碼while ((ret = getopt(argc, argv, "+a:b::c")) != -1)
root@ParseCmdLine:./parse_cmdline -x xxxx -ayyyy -bzzz kkkk
argv[0] ./parse_cmdline
argv[1] -x
argv[2] xxxx
argv[3] -ayyyy
argv[4] -bzzz
argv[5] kkkk
 
./parse_cmdline: invalid option -- x
encountered a unrecognized option: x, argv: -x
option: a argv: yyyy
option: b argv: zzz
 
optind: 4
 
argv[4] xxxx
argv[5] kkkk
 
argv[0] ./parse_cmdline
argv[1] -x
argv[2] -ayyyy
argv[3] -bzzz
argv[4] xxxx
argv[5] kkkk
這塊代碼說明了optstring第一個字符的作用,剩餘的其他功能讀者自己分析;
發佈了0 篇原創文章 · 獲贊 5 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章