最近在看goaccess源码时候,没想到一开头就被getopt_long这个函数给卡住了。。。不禁感慨自己离大牛的差距真是太大了,没办法,慢慢学习积累,希望自己的坚持早晚能导致自己的质变吧。
百度的时候发现了还有getopt这个函数,算是简化版本吧,只支持单字符的命令解析,做linux大型软件开发通常都离不开用户命令参数,下面就来把自己今晚所学到的小小知识点记录下来,以后也能让自己的代码越写越棒!

getopt

  • 以下是摘自manpage中对getopt函数相关参数以及相关变量的展示,接下来对每个参数以及变量进行说明一下

    1
    2
    3
    4
    5
    6
    7
    #include <unistd.h>

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

    extern char *optarg;
    extern int optind, opterr, optopt;
  • argc、argv这两个参数是c语言程序运行的参数变量,通过main函数传递进来,argc代表参数个数,argv是字符串参数数组

  • optstring这个参数是getopt函数所依赖的参数解释字符串,规则是:字符串中的单独一个字符代表了命令行传递的一个参数,字符后面如果没有冒号,则代表此参数没有对应值,如果有一个或者两个冒号,代表了参数后面有值,一个冒号支持两种传递参数值的方法,值紧挨着参数或者与参数隔一个空格,如果有两个冒号,仅支持紧挨着的写法,比如 “ab:c::d”这个字符串:
  • a参数后面没有任何值
  • b参数后面有值,可以通过 -b100或者-b 100方式传递
  • c参数后面有值,只可以通过 -c100的方式传递
  • d参数后面没有任何值
  • optarg这是一个char型指针,指向当前参数的值
  • optind是下一个argv的索引
  • optopt 不知道什么作用….
  • opterr如果不希望getopt()打印出错信息,则只要将全域变量opterr设为0即可。
  • getopt返回值,如果有参数为当前参数字符,没有参数返回-1
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <stdio.h>
    #include <unistd.h>

    int main(int argc,char *argv[]){
    char opt;
    const char *optstring = "ab:c::d";
    while((opt = getopt(argc,argv,optstring)) != -1){
    printf("%c:%s\t",opt,optarg);
    printf("optind=%d\t",optind);
    printf("next opt is %s\t",argv[optind]);
    printf("optopt:%d\n",optopt);
    }
    return 0;
    }

编译之后运行效果如下:

1
2
3
4
5
./app -a -b 200 -c100 -d
a:(null) optind=2 next opt is -b optopt:0
b:200 optind=4 next opt is -c100 optopt:0
c:100 optind=5 next opt is -d optopt:0
d:(null) optind=6 next opt is (null) optopt:0

以上就是getopt的大致用法

getopt_long

getopt_long保留了getopt的用法,并且支持长参数,就是不是单个字符的选项参数

1
2
3
4
5
#include <getopt.h>

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

  • 前三个参数和getopt基本上一致
  • longopts:长参数的结构体配置
  • longindex:如果longindex非空,它指向的变量将记录当前找到参数符合longopts里的第几个元素的描述,即是longopts的下标值
  • 返回值:对于短选项,返回值同getopt函数;对于长选项,如果flag是NULL,返回val,否则返回0;对于错误情况返回值同getopt函数
  • struct option

    1
    2
    3
    4
    5
    6
    struct option {
    const char *name; /* 参数名称 */
    int has_arg; /* 指明是否带有参数 */
    int *flag; /* flag=NULL时,返回value;不为空时,*flag=val,返回0 */
    int val; /* 用于指定函数找到选项的返回值或flag非空时指定*flag的值*/
    };
  • has_arg取值

    1
    2
    3
    no_argument         表明长选项不带参数,如:--name, --help
    required_argument 表明长选项必须带参数,如:--prefix /root或 --prefix=/root
    optional_argument 表明长选项的参数是可选的,如:--help或 –prefix=/root,其它都是错误
  • 下面通过实例代码演示用法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include <stdio.h>
    #include <unistd.h>
    #include <getopt.h>

    int main(int argc,char *argv[]){
    int o,idx = 0;
    const char *short_opts = "abc";
    struct option long_opts[] = {
    {"help",no_argument,NULL,'h'},
    {"ip",optional_argument,NULL,'i'},
    {"port",required_argument,NULL,'p'},
    {NULL,0,NULL,0}
    };
    while((o = getopt_long(argc,argv,short_opts,long_opts,&idx)) != -1){
    printf("%c:%s\t",o,optarg);
    printf("optind=%d\t",optind);
    printf("next opt is %s\n",argv[optind]);
    }
    return 0;
    }

结果

1
2
3
4
5
./app --help  --port=8800 --ip=127.0.0.1

h:(null) optind=2 next opt is --port=8800
p:8800 optind=3 next opt is --ip=127.0.0.1
i:127.0.0.1 optind=4 next opt is (null)