在寫程序的時候,咱們常常須要用到命令行參數,因此今天咱們看看c語言中的getopt()這個函數。數組
咱們先看看下面這個app
int main (int argc,char *argv[]) {ide
......函數
}spa
argc寄存了命令行參數個數(注意:包括程序名自己,也包括咱們後面會提到的選項和選項參數)
命令行
咱們在命令行運行 ./ppyy.sh ok ko pp pe指針
對應的關係是: argv[0] argv[1] argv[2] argv[3] argv[4]get
可是隻是這麼用,對我來講是不夠的,記不記得咱們在命令行常常使用ps -ef這樣的命令,-ef就是命令行選項,它就像開關同樣。string
爲了能具有命令行選項這樣的功能,咱們今天來看看getopt()這個函數。it
首先,咱們來看看一段程序<注:這段源程序來自head first>
#include <stdio.h>
#include <unistd.h> //getopt()在unistd.h這個頭文件中提供
int main(int argc,char *argv[]){
char *delivery = "";
int thick = 0;
int count = 0;
char ch;
while ((ch = getopt(argc,argv,"d:t")) != EOF ){
switch (ch){
case 'd':
delivery = optarg;
break;
case 't':
thick = 1;
break;
default:
fprintf(stderr,"Unknown option:'%s'\n",optarg);
return 1;
}
}
argc -= optind;
argv += optind;
if (thick)
puts("Thick crust.");
if (delivery[0])
printf("To be delivered %s.\n",delivery);
puts("Ingredients:");
for (count=0;count<argc;count++)
puts(argv[count]);
return 0;
}
接下來,咱們逐一來解讀getopt()在這段程序中如何工做的。
while ((ch = getopt(argc,argv,"d:t")) != EOF )
一、首先咱們採用循環來獲取getopt函數的返回值,直到命令行結尾,由於getopt函數沒有選項處理時,是返回-1。
二、getopt()函數中的"d:t",表明d和t是有效選項,同時d後面是有選項參數的,它寄存在optarg這個變量裏面。
switch (ch){
case 'd':
delivery = optarg;
break;
case 't':
thick = 1;
break;
default:
fprintf(stderr,"Unknown option:'%s'\n",optarg);
一、這一段很簡單明瞭了吧,採用switch處理咱們的命令行參數,是d的時候,就把寄存在變量optarg中的選項參數賦值給delivery。
二、default,默認當咱們匹配不上有效的命令行參數的時候,咱們就把它輸出到標準錯誤。
argc -= optind;
argv += optind;
上面這兩個,可能不太好理解,由於咱們須要先弄清楚getopt()這個函數的內部工做原理。
getopt()的函數聲明:int getopt(int argc,char * const argv[ ],const char * optstring);
getopt是從argv[1]到argv[argc-1]進行逐一處理的,它會把選項和選項參數依次放到argv數組裏邊去,再依次把其餘命令行參數放到argv數組中(選項和選項參數的後面)。
舉個例子,若是開始輸入的命令是
./order_pizza -t Anchovies Pineapple -d now
那麼argv[]數組會依次接收他們的值並進行存放,此時argv[]數組是["./order_pizza", "-t","Anchovies", "Pineapple", "-d", "now"] ,可是getopt函數在處理完成後,argv[]數組裏面的順序是["/order_pizza" , "-t" , "-d" , "now" , "Anchovies" ,"Pineapple"]
optind這個變量則保存了getopt()函數處理了幾個選項和選項參數,初始化是1(插一句,爲何初始化是1不是0呢,由於咱們須要考慮程序自己,這個在argv中的數組元素),因此若是讀取了3個選項和選項參數,則getopt函數處理完成之後,optind的值是4。
ok,如今回過頭來看上面的argc -= optind;和argv += optind; 它的意思是,在getopt函數處理完成後,讓咱們跳過已經處理過的命令行選項和選項參數,因此此時的argc=2,而argv須要前進4位(數組地址變更)。
if (thick)
puts("Thick crust.");
if (delivery[0])
printf("To be delivered %s.\n",delivery);
puts("Ingredients:");
for (count=0;count<argc;count++)
puts(argv[count]);
這上面的代碼就很簡單了,基本不用咱們解釋了。
補充,是關於getopt函數聲明中,對optstring這個參數的處理:
1) 單個字符,表示選項。
2) 單個字符後接一個冒號」:」,表示該選項後必須跟一個選項參數。參數緊跟在選項後或者以空格隔開。該參數的指針賦給optarg。
3) 單個字符後跟兩個冒號」:」,表示該選項後必須跟一個選項參數。參數必須緊跟在選項後不能以空格隔開。該參數的指針賦給optarg。(這個特性是GNU的擴展)。
另外,還有optopt和opterr這些變量,不過上面的已經足夠咱們理解getopt()這個函數的核心了。