初學getopt

傳遞命令行參數的程序是一種標準的UNIX程序,現在各種APP滿天飛,誰還弄那??? 也許是吧,不過學了這麼長時間的C, 總感覺要寫一些能用的程序出來,克隆克隆GNU的一些小工具吧,如果能做到的話。

getopt是一種接口,提供了一個可以讓用戶更簡單的處理命令行參數的方法,根據Eric Raymond的話來說,是由於這個特性,是的不同的程序之間可以交互(扯遠了。。。)

<getopt.h> 和 <unistd.h>中提供了一些函數,最重要的是:


int getopt(int argc, char * const argv[], const char *optstring);

int getopt_long(int argc, char * const argv[], const char *optstring,
                   const struct option *longopts, int *longindex);

//還有一些全局變量,諸如:
int optopt, optind, opterr;
char *optarg;





<getopt.h>中還有一個函數, getopt_long_only, 不過我覺的暫時用不到。

getopt_long 是 getopt 的超集,同時它還能處理長參數,我不會說的詳細的像GNU DOC一樣,說一下它有用的地方;

1. optstring語句:

    它就是一個字符串,包含所有的短參數,eg: ":abc:d::"

    第一個字符表示表示如何處理缺少optarg的情況,這樣可以和unrecognized option情況區分(見下文);

    單個字母表示就是參數啦, 如果一個字母后面有一個冒號(colon),那麼該參數必須有一個子參數,如果有倆,說明子參數是 可選的;

    如果字母W後有一個分號(semicolon),還必須是W,就把 -W foo 看成 long option,這個幾乎用不到,我們有getopt_long了。

2. struct option

struct option {
const char *name;
int      has_arg;
int      *flag;
int      val;
}


    第一個 name是名字;

    第二個 has_arg是個標誌, 有no_argument, required_argument, optional_argument 三種;

    第三個 flag 說明如何處理參數,這是個指針。。。 如果指向NULL說明返回val的值, 如果長參數和短參數意義相同,那就簡單了;

    如果不是NULL,那麼getopt_long返回0, flag指向了一個和val相同的地址,否則不變。

    返回0的時候可以通過longindex來定位,它會指向我們遇到的了哪個參數; 這樣就方便我們那些只有長參數的參數了。。。

eg:

static struct option long_options[] = {
                   {"add",     required_argument, 0,  0 },
                   {"append",  no_argument,       0,  0 },
                   {"delete",  required_argument, 0,  0 },
                   {"verbose", no_argument,       0,  0 },
                   {"create",  required_argument, 0, 'c'},
                   {"file",    required_argument, 0,  0 },
                   {0,         0,                 0,  0 }
               };



3.我們用這兩個函數的時候都是用switch語句,

while ((c = getopt(argc, argv, optstring)) != -1) {
    switch(c) {
        case 'a': //....
    }
}
//或者
while (1) {
    c = getopt_long(argc, argv, optstring, longopts, &longindex);
    if (c == -1)
        break;
    switch (c) {
        case ' ':  //...
    }
}




來工作的,返回的是我們遇到的參數, 遇到第一個非參數時返回-1; 這樣我們跳出循環, 當然還有其他情況, 總結一下所有情況:

1:遇到 不是以 ‘-' 和 ‘--’ 開始的argv[i]表示遍歷完參數了;

2:遇到 單個參數 '--' 說明參數終止,以後的都是非參數變量;

3:遇到不認識的參數 返回 '?' 遇到參數少子參數默認也返回'?', 不過我們可以更改optstring的第一個字符;

返回'?'後,將有問題的參數 給 optopt,把錯誤信息給opterr;


4.遍歷完所有參數:

接下來optind會指向第一個非參數變量,知道 optind == argc 這樣 argv[optind] = ‘\0';

總的來說 getopt還是很好用的,在 gnu的實現裏面,使用getopt_long一個函數實現了getopt和getopt_long_only兩者,這是後話了,我們使用的時候就是設置一些標誌位,然後根據參數跳到某個函數去,順便吐槽下GNU的庫函數的實現,實在是太難懂了。。。


這是我寫的第一篇博客,從基本的東西做起,把自己的學習記錄下來,就像日記一樣。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章