C/C++ getopt()函数的介绍及使用
函數(shù)原型:
int getopt(int argc,char * const argv[ ],const char * optstring);
前兩個(gè)參數(shù)大家不會(huì)陌生,沒(méi)錯(cuò),就是老大main函數(shù)的兩個(gè)參數(shù)!老大傳進(jìn)來(lái)的參數(shù)自然要有人接著!
第三個(gè)參數(shù)是個(gè)字符串,看名字,我們可以叫他選項(xiàng)字符串(后面會(huì)說(shuō)明)
返回值為int類(lèi)型,我們都知道char類(lèi)型是可以轉(zhuǎn)換成int類(lèi)型的,每個(gè)字符都有他所對(duì)應(yīng)的整型值,其實(shí)這個(gè)返回值返回的就是一個(gè)字符,什么字符呢,叫選項(xiàng)字符(姑且這么叫吧,后面會(huì)進(jìn)一步說(shuō)明)
在此之前還要介紹他的幾個(gè)兄弟
小弟1:extern char* optarg;
小弟2:extern int optind;
小弟3:extern int opterr;
小弟4:extern int optopt;
- 小弟1是用來(lái)保存選項(xiàng)的參數(shù)的(先混個(gè)臉熟,后面有例子);
- 小弟2用來(lái)記錄下一個(gè)檢索位置;
- 小弟3表示的是是否將錯(cuò)誤信息輸出到stderr,為0時(shí)表示不輸出,
- 小弟4表示不在選項(xiàng)字符串optstring中的選項(xiàng)(有點(diǎn)亂哈,后面會(huì)有例子)
問(wèn)題1:選項(xiàng)到底是個(gè)什么鬼?
? ? ? ? 在linux下大家都用過(guò)這樣一條指令吧:gcc helloworld.c -o helloworld.out;?這條指令中的-o就是命令行的選項(xiàng),而后面的helloworld.out就是-o選項(xiàng)所攜帶的參數(shù)。當(dāng)然熟悉shell指令的人都知道(雖然我并不熟悉),有些選項(xiàng)是不用帶參數(shù)的,而這樣不帶參數(shù)的選項(xiàng)可以寫(xiě)在一起(這一點(diǎn)在后面的例子中會(huì)用到,希望理解),比如說(shuō)有兩個(gè)選項(xiàng)-c和-d,這兩個(gè)選項(xiàng)都不帶參數(shù)(而且明顯是好基友),那么他們是可以寫(xiě)在一起,寫(xiě)成-cd的。實(shí)際的例子:當(dāng)我們刪除一個(gè)文件夾時(shí)可以使用指令?rm 目錄名 -rf,本來(lái)-r表示遞歸刪除,就是刪除文件夾中所有的東西,-f表示不提示就立刻刪除,他們兩個(gè)都不帶參數(shù),這時(shí)他們就可以寫(xiě)在一起。
問(wèn)題2:選項(xiàng)字符串又是何方神圣?
? ? ? ? "a:b:cd::e",這就是一個(gè)選項(xiàng)字符串。對(duì)應(yīng)到命令行就是-a ,-b ,-c ,-d, -e 。冒號(hào)又是什么呢??冒號(hào)表示參數(shù),一個(gè)冒號(hào)就表示這個(gè)選項(xiàng)后面必須帶有參數(shù)(沒(méi)有帶參數(shù)會(huì)報(bào)錯(cuò)哦),但是這個(gè)參數(shù)可以和選項(xiàng)連在一起寫(xiě),也可以用空格隔開(kāi),比如-a123 和-a ? 123(中間有空格) 都表示123是-a的參數(shù);兩個(gè)冒號(hào)的就表示這個(gè)選項(xiàng)的參數(shù)是可選的,即可以有參數(shù),也可以沒(méi)有參數(shù),但要注意有參數(shù)時(shí),參數(shù)與選項(xiàng)之間不能有空格(有空格會(huì)報(bào)錯(cuò)的哦),這一點(diǎn)和一個(gè)冒號(hào)時(shí)是有區(qū)別的。
好了,先給個(gè)代碼,然后再解釋吧。
#include <unistd.h> #include <stdio.h> int main(int argc, char * argv[]) {int ch;printf("\n\n");printf("optind:%d,opterr:%d\n",optind,opterr);printf("--------------------------\n");while ((ch = getopt(argc, argv, "ab:c:de::")) != -1){printf("optind: %d\n", optind);switch (ch) {case 'a':printf("HAVE option: -a\n\n"); break;case 'b':printf("HAVE option: -b\n"); printf("The argument of -b is %s\n\n", optarg);break;case 'c':printf("HAVE option: -c\n");printf("The argument of -c is %s\n\n", optarg);break;case 'd':printf("HAVE option: -d\n");break;case 'e':printf("HAVE option: -e\n");printf("The argument of -e is %s\n\n", optarg);break;case '?':printf("Unknown option: %c\n",(char)optopt);break;}}}編譯后命令行執(zhí)行:# ./main -b "qing er"
輸出結(jié)果為:
optind:1,opterr:1
--------------------------
optind: 3
HAVE option: -b
The argument of -b is qing er
?
? ? ? ? 我們可以看到:optind和opterr的初始值都為1,前面提到過(guò)opterr非零表示產(chǎn)生的錯(cuò)誤要輸出到stderr上。那么optind的初值為什么是1呢?
? ? ? ? 這就要涉及到main函數(shù)的那兩個(gè)參數(shù)了,argc表示參數(shù)的個(gè)數(shù),argv[]表示每個(gè)參數(shù)字符串,對(duì)于上面的輸出argc就為3,argv[]分別為: ./main 和 -b 和"qing er" ,實(shí)際上真正的參數(shù)是用第二個(gè)-b 開(kāi)始,也就是argv[1],所以optind的初始值為1;
? ? ? ? 當(dāng)執(zhí)行g(shù)etopt()函數(shù)時(shí),會(huì)依次掃描每一個(gè)命令行參數(shù)(從下標(biāo)1開(kāi)始),第一個(gè)-b,是一個(gè)選項(xiàng),而且這個(gè)選項(xiàng)在選項(xiàng)字符串optstring中有,我們看到b后面有冒號(hào),也就是b后面必須帶有參數(shù),而"qing er"就是他的參數(shù)。所以這個(gè)命令行是符合要求的。至于執(zhí)行后optind為什么是3,這是因?yàn)閛ptind是下一次進(jìn)行選項(xiàng)搜索的開(kāi)始索引,也是說(shuō)下一次getopt()函數(shù)要從argv[3]開(kāi)始搜索。當(dāng)然,這個(gè)例子argv[3]已經(jīng)沒(méi)有了,此時(shí)getopt()函數(shù)就會(huì)返回-1。
再看一個(gè)輸入:
?./main -b "qing er" -c1234
輸出結(jié)果為:
optind:1,opterr:1
--------------------------
optind: 3
HAVE option: -b
The argument of -b is qing er
optind: 4
HAVE option: -c
The argument of -c is 1234
? ? ? ? 對(duì)于這個(gè)過(guò)程會(huì)調(diào)用三次getopt()函數(shù),和第一個(gè)輸入一樣,是找到選項(xiàng)-b和他的參數(shù)"qing er",這時(shí)optind的值為3,也就意味著,下一次的getopt()要從argv[3]開(kāi)始搜索,所以第二次調(diào)用getopt()函數(shù),找到選項(xiàng)-c和他的參數(shù)1234(選項(xiàng)和參數(shù)是連在一起的),由于-c1234寫(xiě)在一起,所以他兩占一起占用argv[3],所以下次搜索從argv[4]開(kāi)始,而argv[4]為空,這樣第三次調(diào)用getopt()函數(shù)就會(huì)返回-1,循環(huán)隨之結(jié)束。
接下來(lái)我們看一個(gè)錯(cuò)誤的命令行輸入:?./main -z 123
輸出為:
optind:1,opterr:1
--------------------------
./main: invalid option -- 'z'
optind: 2
Unknown option: z
其中./main: invalid option -- 'z'就是輸出到stderr的錯(cuò)誤輸出。如果把opterr設(shè)置為0那么就不會(huì)有這條輸出。
在看一個(gè)錯(cuò)誤的命令行輸入:?./main -zheng
optind:1,opterr:1
--------------------------
./main: invalid option -- 'z'
optind: 1
Unknown option: z
./main: invalid option -- 'h'
optind: 1
Unknown option: h
optind: 2
HAVE option: -e
The argument of -e is ng
前面提到過(guò)不帶參數(shù)的選項(xiàng)可以寫(xiě)在一起,所以當(dāng)getopt()找到-z的時(shí)候,發(fā)現(xiàn)在optstring 中沒(méi)有,這時(shí)候他就認(rèn)為h也是一個(gè)選項(xiàng),也就是-h和-z寫(xiě)在一起了,依次類(lèi)推,直到找到-e,發(fā)現(xiàn)optstring中有。
? ? ? ?
? ? ? ? 最后要說(shuō)明一下,getopt()會(huì)改變argv[]中參數(shù)的順序。經(jīng)過(guò)多次getopt()后,argv[]中的選項(xiàng)和選項(xiàng)的參數(shù)會(huì)被放置在數(shù)組前面,而optind 會(huì)指向第一個(gè)非選項(xiàng)和參數(shù)的位置。看例子
#include <unistd.h> #include <stdio.h> int main(int argc, char * argv[]) {int i;printf("--------------------------\n");for(i=0;i<argc;i++){printf("%s\n",argv[i]);}printf("--------------------------\n");//int aflag=0, bflag=0, cflag=0;int ch;printf("\n\n");printf("optind:%d,opterr:%d\n",optind,opterr);printf("--------------------------\n");while ((ch = getopt(argc, argv, "ab:c:de::")) != -1){printf("optind: %d\n", optind);switch (ch) {case 'a':printf("HAVE option: -a\n\n"); break;case 'b':printf("HAVE option: -b\n"); printf("The argument of -b is %s\n\n", optarg);break;case 'c':printf("HAVE option: -c\n");printf("The argument of -c is %s\n\n", optarg);break;case 'd':printf("HAVE option: -d\n");break;case 'e':printf("HAVE option: -e\n");printf("The argument of -e is %s\n\n", optarg);break;case '?':printf("Unknown option: %c\n",(char)optopt);break;}}printf("----------------------------\n");printf("optind=%d,argv[%d]=%s\n",optind,optind,argv[optind]);printf("--------------------------\n");for(i=0;i<argc;i++){printf("%s\n",argv[i]);}printf("--------------------------\n");}命令行:./main zheng -b "qing er" han -c123 qing
輸出結(jié)果為:
--------------------------
./main
zheng
-b
qing er
han
-c123
qing
--------------------------
optind:1,opterr:1
--------------------------
optind: 4
HAVE option: -b
The argument of -b is qing er
optind: 6
HAVE option: -c
The argument of -c is 123
----------------------------
optind=4,argv[4]=zheng
--------------------------
./main
-b
qing er
-c123
zheng
han
qing
--------------------------
可以看到最開(kāi)始argv[]內(nèi)容為:
./main
zheng
-b
qing er
han
-c123
qing
?
在執(zhí)行了多次getopt后變成了
./main
-b
qing er
-c123
zheng
han
qing
? ? ? ? 我們看到,被getopt挑出的選項(xiàng)和對(duì)應(yīng)的參數(shù)都按順序放在了數(shù)組的前面,而那些既不是選項(xiàng)又不是參數(shù)的會(huì)按順序放在后面。而此時(shí)optind為4,即指向第一個(gè)非選項(xiàng)也非選項(xiàng)的參數(shù),zheng
總結(jié)
以上是生活随笔為你收集整理的C/C++ getopt()函数的介绍及使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Java 集合List、Set、Hash
- 下一篇: Python之struct介绍及详解(与