getopt_long, getopt_long_only -- 命令行解析函數,支持長選項解析
【說明】getopt_long/getopt_long_only是getopt的泛集,getopt是getopt_long的一個子集,getopt支持的所有特性,getopt_long都支持,包括錯誤打印、argv元素順序調整等;getopt_long相比getopt增加了長選項的解析,具體如下:
1、形如:cmd [--create][--file] //對長選項的解析;
2、形如:cmd [--create a_argument][-file b_argument] //對長選項及長選項的參數解析;
3、形如:cmd [--create [a_argument]] //選項create的參數也是可選的情況解析
getopt_long_only與getopt_long的區別在於:getopt_long僅僅只能將"--"開始的選項視為長選項,但getopt_long_only將"-"開頭選項也會視為長選項,當長選項列表均不滿足時,且短選項滿足時,"-"才會解析為短選項;
原型:
#define _GNU_SOURCE #include <getopt.h> extern char *optarg; extern int optind, opterr, optopt; int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex); int getopt_long_only(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex);
描述:
1、注意相比getopt,使用getopt_long需要加頭文件
<getopt.h>;
2、getopt_long除了會接受長選項,其他概念和getopt是一樣的;
3、如果使用getopt_long想只接受短選項,設置longopts為NULL即可;如果只想接受長選項,相應地設置optstring為NULL即可;
4、長選項名是可以使用縮寫方式,比如:選項有--file\--create,那么輸入--c/--cr/--cre等均會被正確識別為create選項;
5、對於帶參數的長選項格式是:--arg=param或--arg param;
6、
longopts是指向struct option數組的第一個元素的指針,struct option定義在<getopt.h>中;
7、
longindex如果非NULL,則是返回識別到struct option數組中元素的位置指針;
struct option的說明:
/*
name: 長選項名
has_arg: 是否帶參數或可選參數,這個值在getopt.h中有宏定義,如下:
# define no_argument 0
# define required_argument 1
# define optional_argument 2
flag: 確定函數返回值的情況,如果flag==NULL,則識別選項后返回val(常用的如:設置val為長命令的短命令字符);否則,識別后getopt_long返回0,flag指向一個設置到val的變量;
val: 設置為返回值,或者是flag指向的變量;這里要
注意不要寫-1到val,否則其作用是getopt_long返回-1,然后停止解析選項;
[注意] longopts的最后一個元素必須是全0填充,否則會報段錯誤
*/
struct option {
const char *name;
int has_arg;
int *flag;
int val;
};
返回值:
1、如果識別短選項,同getopt一樣返回短選項字符;
2、如果識別長選項,根據flag的設置返回不同的內容,一般flag都設置為NULL,返回val;
3、如果發生錯誤,如:未識別選項或者必須加參數的選項丟失參數,返回'?',如果在optstring中設置了第一個字符為':',丟失參數返回':',這個同getopt返回時一樣的;
4、當縮寫長選項引起歧義時或者不需要的選項強加了參數,都會返回'?';
5、返回-1表示選項處理全部結束;
6、如果在輸入的argv[]中包含了獨立的"--"字符串,同getopt一樣,解析到這里返回-1,停止選項的解析;
測試實例:
#include <stdio.h> #include <stdlib.h> #include <getopt.h> int main(int argc, char **argv) { extern char *optarg; extern int optind, opterr, optopt; int c; int digit_optind = 0; while (1) { int this_option_optind= optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"add", required_argument, NULL, 0}, {"append", no_argument, NULL, 0}, {"delete", required_argument, NULL, 0}, {"verbose", no_argument, NULL, 0}, {"create", required_argument, NULL, 'c'}, {"file", required_argument, NULL, 0}, {0, 0, 0, 0}, }; c = getopt_long(argc, argv, ":abc:d:012", long_options, &option_index); if (c == -1) break; switch (c) { case 0: printf ("option %s", long_options[option_index].name); if (optarg) printf (" with arg %s", optarg); printf ("\n"); break; case '0': case '1': case '2': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value \"%s\"\n", optarg); break; case 'd': printf ("option d with value \"%s\"\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit(0); }
運行自行操作測試