linux系統getopt函式詳解

wangpengqi發表於2012-11-14

getopt()函式就是用來解析命令列引數

呼叫形式一般如下:
  1. while((= getopt(argc, argv, "xy:z::")) != -1){
  2.       switch(c){
  3.       case 'x':   ... ...
  4.       case 'y':   ... ...
  5.       case 'z':   ... ...
  6.       ... ....
  7.       }
  8. }
  9. ... ....
getopt函式的原型如下:
  1. #include <unistd.h>
  2. int getopt(int argc, char * const argv[], const char *optstring);
  3. extern char *optarg; 
    extern 
    int optind,  // 初始化值為1,下一次呼叫getopt時,從optind儲存的位置重新開始檢查選項。 
    extern int opterr,  // 初始化值為1,當opterr=0時,getopt不向stderr輸出錯誤資訊。
    extern int optopt;  // 當命令列選項字元不包括在optstring中或者選項缺少必要的引數時,
                                        
    // 該選項儲存在optopt中, getopt返回'?’。
getopt()函式用於解析命令列引數。

optarg和optind是兩個最重要的external 變數。optarg是指向引數的指標(當然這隻針對有引數的選項);
optind是argv[]陣列的索引,眾所周知,argv[0]是函式名稱,所有引數從argv[1]開始,所以optind被初始化設定指為1。       
每呼叫一次getopt()函式,返回一個選項,如果該選項有引數,則optarg指向該引數。
 在命令列選項引數再也檢查不到optstring中包含的選項時,返回-1。
字串optstring,它是作為選項的字串的列表。
函式getopt()認為optstring中,以'-’開頭的字元(注意!不是字串!!)就是命令列引數選項,
有的引數選項後面可以跟引數值。optstring中的格式規範如下:
1) 單個字元,表示選項,
2) 單個字元後接一個冒號”:”,表示該選項後必須跟一個引數值。引數緊跟在選項後或者以空格隔開。該引數的指標賦給optarg。
3) 單個字元後跟兩個冒號”::”,表示該選項後必須跟一個引數。引數必須緊跟在選項後不能以空格隔開。該引數的指標賦給optarg。
getopt()函式的第三個引數optstring是一個有所有合法的“可選字元”所組成的字串。
《1》在引數optstring的“可選字元”如果後面帶有一個':',則表示在該“可選字元”的後面必須有一個引數
比如“o:"表示: gcc -o arg 在-o的後面必須帶有一個引數arg. 在getopt()函式解析完"o:"對應的命令列引數時,char型的指標optarg則指向了參數"arg"
《2》如果在“可選字元”的後面帶有了兩個':'時,則表示在該“可選字元”後面可能有也可能沒有引數,有引數,則optarg指向引數,沒有則為0。這是GNU的一個關於getopt()函式的擴充套件。
《3》如果optstring中含有一個大寫的'W'字元,後面帶有一個冒號,也就是形如"W:",則表示該“可選字元”是一個“長選項”,也就是說不是隻有一個字元的“可選字元”。比如:gcc -Wall  hello.c 要解析該命令列,getopt()函式中的第三個引數optstring應該是:"W:all",而且當解析到“-Wall"時optarg = "all".  這一點也是GNU對getopt()函式的擴充套件。
《4》如果getopt()函式在argv中解析到一個沒有包含在optstring中的“可選字元”,它會列印一個錯誤資訊,並將該“可選字元”儲存在optopt中,並返回字元'?'。當然,我們可以將變數opterr賦值為0,來阻止getopt()函式輸出錯誤資訊
《5》當getopt()函式的第三個引數optstring的第一個字元是':'時,很顯然,這是由於少寫了一個"可選字元"的緣故。此時,getopt()函式不返回'?',而是返回':'來暗示我們漏掉了一個”可選字元”.

  1. #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    int main(int argc, char *argv[])
    {
            int c;
            opterr = 0; 
            while((c = getopt(argc, argv, "Oo:W:all")) != -1){
                    printf("option char: %c\n", c);
                    switch(c){
                    case 'O':
                            printf("optimization flag is open.\n\n");
                            break;
                    case 'o':
                            printf("the obj is: %s\n\n", optarg);
                            break;
                    case 'W':
                            printf("optarg: %s\n\n", optarg);
                            break;        
                    case '?':
                            fprintf(stderr, "Usage: %s [-Wall] [-O] [-o arg] arg\n", argv[0]);
                            break;
                    case ':':
                            fprintf(stderr, "miss option char in optstring.\n");
                            break;
                    }
            }
            exit(0);
    }
    編譯:gcc -Wall -o mygcc gcc.c
    執行:./mygcc -Wall -O -o mygcc
    結果:
    option char: W
    optarg: all

    option char: O
    optimization flag is open.

    option char: o
    the obj is: mygcc
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    int main(int argc, char *argv[])
    {
            int c;
    
            // opterr = 0; 
            while((c = getopt(argc, argv, "iu:z:")) != -1){
                  switch(c){
                  case 'i':
                     printf("current option index:(optind-1)=%d, argv[optind-1]=argv[%d]=%s\n",
                                    (optind-1), (optind-1), argv[optind-1]);
                     printf("next option index:(optind)=%d, argv[optind]=argv[%d]=%s\n",
                                    (optind), (optind), argv[optind]);
                     printf("optarg=%s, opterr=%d, optopt=%d\n\n", optarg, opterr, optopt);
                     break;
    
                 case 'u':
                     printf("current option index:(optind-2)=%d, argv[optind-2]=argv[%d]=%s\n",
                                    (optind-2), (optind-2), argv[optind-2]);
                     printf("next option index:(optind)=%d, argv[optind]=argv[%d]=%s\n",
                                    (optind), (optind), argv[optind]);
                     printf("optarg=%s, opterr=%d, optopt=%d\n\n", optarg, opterr, optopt);
                     break;
    
                 case 'z':
                     printf("current option index:(optind-1)=%d, argv[optind-1]=argv[%d]=%s\n",
                                    (optind-1), (optind-1), argv[optind-1]);
                     printf("next option index:(optind)=%d, argv[optind]=argv[%d]=%s\n",
                                    (optind), (optind), argv[optind]);
                     printf("optarg=%s, opterr=%d, optopt=%d\n\n", optarg, opterr, optopt);
                     break;
    
                 case '?':
                     fprintf(stderr, "Usage: %s [-i] [-u username] [-z filename]\n", argv[0]);
                     break;
                    }
            }
            exit(0);
    }
    編譯:gcc -Wall -o getopt2 getopt2.c
    執行:./getopt2 -i -u username -z filename
    結果:
    current option index:(optind-1)=1, argv[optind-1]=argv[1]=-i
    next option index:(optind)=2, argv[optind]=argv[2]=-u
    optarg=(null), opterr=1, optopt=0

    current option index:(optind-2)=2, argv[optind-2]=argv[2]=-u
    next option index:(optind)=4, argv[optind]=argv[4]=-z
    optarg=username, opterr=1, optopt=0

    current option index:(optind-1)=5, argv[optind-1]=argv[5]=filename
    next option index:(optind)=6, argv[optind]=argv[6]=(null)
    optarg=filename, opterr=1, optopt=0





相關文章