轉載——getopt函數的使用

來源:互聯網
上載者:User

 

轉載——getopt函數的使用2007-12-16 12:15

 

作者寫得很好。

每一天你都在使用大量的命令列程式,是不是感覺那些命令列參數用起來比較方便,他們都是使用getopt來實現的。
在Linux下使用getopt寫程式是一種比較cool的事情,下面來簡單的介紹一下getopt的使用。

=== getopt使用 ===

在討論參數處理之前,我們先明確兩個概念:選項、選項參數
gcc -g -o test test.c
我們經常使用上面的命令來編譯器,這裡g和o就是選項,其中test就是o的選項參數

下面我們來看一下getopt:

首先是函式宣告:
#include <unistd.h>
extern char *optarg;
extern int optind;
extern int optopt;
extern int opterr;
extern int optreset;
int getopt(int argc, char * const *argv, const char *optstring);

直接看一個例子:
/* getopt.c */
#include <unistd.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
    int aflag=0, bflag=0, cflag=0;
    int ch;
    while ((ch = getopt(argc, argv, "ab:c")) != -1)
    {
        printf("optind: %d\n", optind);
        switch (ch) {
        case 'a':
            printf("HAVE option: -a\n");
            aflag = 1;
            break;
        case 'b':
            printf("HAVE option: -b\n");
            bflag = 1;
            printf("The argument of -b is %s\n", optarg);
            break;
        case 'c':
            printf("HAVE option: -c");
            cflag = 1;
            break;
        case '?':
            printf("Unknown option: %c\n",(char)optopt);
            break;
        }
    }
}

通過上面的例子,大家應該可以照貓畫虎,就可以在自己的程式中使用getopt函數了。

getopt()每調用一次返回一個選項。
argc 和 argv 很顯然就是 main 函數的兩個參數。
字串 optstring 可以包含下列元素:單個字元,字元後面接一個冒號說明後面跟隨一個選項參數,字元後面接兩個冒號說明後面跟隨一個可有可無的選項參數。例如,一個選項字元 "x" 表示選項 "-x" ,選項字元 "x:" 表示選項和其參數 "-x argument",選項字元 "x::" 表示選項 x 的參數是可選的(“::” 是 GNU 增加的,不一定在所有的UNIX 系統下都可以使用)。
getopt()的返回後,如果有選項參數的話 optarg 指向選項參數,並且變數 optind 包含下一個 argv 參數作為對 getopt() 下一次調用的索引。變數 optopt 儲存最後一個由 getopt() 返回的已知的選項。
當參數列已經到結尾時getopt()函數返回-1,當遇到一個未知的選項時 getopt 返回'?'。參數列中選項的解釋可能會被'--'取消,由於它引起 getopt()給參數處理髮送結束訊號並返回-1。

很多時候,我們不希望輸出任何錯誤資訊,或更希望輸出自己定義的錯誤資訊。可以採用以下兩種方法來更改getopt()函數的出錯資訊輸出行為:
在調用getopt()之前,將opterr設定為0,這樣就可以在getopt()函數發現錯誤的時候強制它不輸出任何訊息。
如果optstring參數的第一個字元是冒號,那麼getopt()函數就會保持沉默,並根據錯誤情況返回不同字元,如下:
“無效選項” ―― getopt()返回'?',並且optopt包含了無效選項字元(這是正常的行為)。
“缺少選項參數” ―― getopt()返回':',如果optstring的第一個字元不是冒號,那麼getopt()返回'?',這會使得這種情況不能與無效選項的情況區分開。
例如optstring為:a:b::c,表示a帶一個參數,b可選,c不帶參數
如果輸入d,“無效選項“,getopt返回'?'
如果輸入的a忘記帶參數,“缺少選項參數”,getopt應返':' ;如果不再optstring的第一個字元不是':'的話,那麼將會把這個錯當成"無效參數",從而getopt返回'?';從而無法區別錯誤類型

比如:
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt -a -d -b foo
optind: 2
HAVE option: -a
./getopt: invalid option -- d
optind: 3
Unknown option: d
optind: 5
HAVE option: -b
The argument of -b is foo
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt -a -- -c -b foo
optind: 2
HAVE option: -a

getopt 的原始碼在下面,getopt 將只會解釋到 -a。

變數opterr和optind都被初始化為1。如果想要略去命令列的前幾個參數,可以在調用getopt()前將optind設成其他值。
如果不希望getopt()輸出出錯資訊,將全域變數 opterr 設為 0 即可。

是不是使用比較簡單啊!

=== getopt_long使用 ===

我敢說,幾乎每個人在接觸到一個新的命令的時候,第一件乾的事情就是 cmd -h 或者是 cmd --help,-h我們都知道是使用getopt來實現的,那麼--help是怎麼實現的呢?那就是getopt_long了,他可以支援長參數

先看一個例子程式:
#include <stdio.h>
#include <getopt.h>

int do_name, do_gf_name;
char *l_opt_arg;

static const char *shortopts = "l:ng";
struct option longopts[] = {
{"name", no_argument, NULL, 'n'},
{"gf_name", no_argument, NULL, 'g'},
{"love", required_argument, NULL, 'l'},
{0, 0, 0, 0},
};

int main (int argc, char *argv[])
{
int c;

while ((c = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1)
    {
      switch (c)
   {
   case 'n':
      printf ("My name is LYR.\n");
      break;
   case 'g':
      printf ("Her name is BX.\n");
      break;
   case 'l':
      l_opt_arg = optarg;
      printf ("Our love is %s!\n", l_opt_arg);
      break;
   }
    }
return 0;
}

代碼中我們使用getopt_long來實現長選項的解析,其中我們使用了一個結構體struct options的數組,struct options longopt[].
struct options的定義如下:
struct option{
     const char *name;
     int has_arg;
     int *flag;
     int val;
};

對結構中的各元素解釋如下:
    const char *name
    這是選項名,前面沒有虛線。譬如"help"、"verbose"之類。

    int has_arg
    描述了選項是否有選項參數。如果有,是哪種類型的參數,此時,它的值一定是下表中的一個。
    符號常量    數值    含義
    no_argument    0    選項沒有參數
    required_argument    1    選項需要參數
    optional_argument    2    選項參數可選

    int *flag
    如果這個指標為NULL,那麼 getopt_long()返回該結構val欄位中的數值。如果該指標不為NULL,getopt_long()會使得它所指向的變數中填入val欄位中的數值,並且getopt_long()返回0。如果flag不是NULL,但未發現長選項,那麼它所指向的變數的數值不變。

    int val
    這個值是發現了長選項時的傳回值,或者flag不是NULL時載入*flag中的值。典型情況下,若flag不是NULL,那麼val是個真/假值,譬如1或0;另一方面,如果flag是NULL,那麼 val通常是字元常量,若長選項與短選項一致,那麼該字元常量應該與optstring中出現的這個選項的參數相同。

    每個長選項在長選項表中都有一個單獨條目,該條目裡需要填入正確的數值。數組中最後的元素的值應該全是0。數組不需要排序,getopt_long()會進行線性搜尋。但是,根據長名字來排序會使程式員讀起來更容易。

下面,我們看一下程式中的這個結構:
struct option longopts[] = {
{"name", no_argument, NULL, 'n'},
{"gf_name", no_argument, NULL, 'g'},
{"love", required_argument, NULL, 'l'},
{0, 0, 0, 0},
};
結構說明了三個常選項,name、gf_name、love三個選項,其中love需要選項;它們分別對應的短選項是n、g、l。
注意:上面結構體數組中的結構體的第三個參數flag都為NULL.

程式運行結果:
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt_long --name
My name is LYR.
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt_long -n
My name is LYR.
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt_long -l me
Our love is me!
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt_long --love me
Our love is me!
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$

=== Reference ===
GNU提供的getopt()函數的特點

http://blog.csdn.net/realduke2000/archive/2007/10/05/1812126.aspx

使用 getopt() 進行命令列處理

http://www.ibm.com/developerworks/cn/aix/library/au-unix-getopt.html

=== Questions ===
1、如何在getopt中指定選擇性參數
2、能否實現使用一個選項帶多個參數,例如 scanner -i 1.1.1.1 2.2.2.2 3.3.3.3

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.