热门搜索:  

命令行参数处理-getopt()和getopt_long()

在实际编程当中,自己编写代码处理命令行参数是比较麻烦且易出错的。一般我们会直接使用getopt()getopt_long()函数,下文将介绍具体的使用方法。

getopt()

getopt()用于处理”单字母“选项,如-a, -t等。函数声明如下:

#include <unistd.h>                                              
int getopt(int argc, char *const argv[], const char *optstring);
   
extern char *optarg;
extern int optind, opterr, optopt;

参数说明

对于前两个参数argcgrgv[],一般直接使用main()传递进来的数值。用过C语言的同学应该比较熟悉,简单复习一下。

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char const *argv[])
{
    //在C99标准推出之前,变量不能在for()声明,为了兼容性,这里提前声明"i"
    int i;
    printf("argc = %d
", argc);

    if (argc > 1)
    {
        for (i = 0; i < argc; ++i)
        {   
            printf("argv[%d] = %s
", i, argv[i]);
        }
    }
    return 0;
}

argc: argument count, 记录了命令行参数的个数(包括命令本身)

argv: argument vector, 记录了命令行参数的具体内容

$ ./test 1 2 3
argc = 4 
argv[0] = ./test
argv[1] = 1
argv[2] = 2
argv[3] = 3

optstring: 作为getopt()的第三个参数,用于规定合法选项(option)以及选项是否带参数(argument)。一般为合法选项字母构成的字符串,如果字母后面带上冒号:就说明该选项必须有参数。如"ht:"说明有两个选项-h-t且后者(-t)必须带有参数(如-t 60)。

返回值

  • option character: 一般情况下,getopt()读取到合法选项,就返回该选项(一个字母)。
  • -1:结束标志。
while ( (opt = getopt(argc, argv, "ab:") ) != -1) {...}
  • ?: 一般情况下,遇到非法选项或者参数缺失都会返回?。如果需要区分这两种错误,可以在optstring开头加上:,如:ht: , 这样参数缺失就返回:,非法选项就返回?。
  • ::在optstring参数开头第一个字符为:时,遇到参数缺失返回:。参考下方代码(摘自Linux Programming by Example)可帮助理解
int oc;             /* option character */
char *b_opt_arg;

while ((oc = getopt(argc, argv, ":ab:")) != -1) {
    switch (oc) {
    case "a":
        /* handle -a, set a flag, whatever */
        break;
    case "b":
        /* handle -b, get arg value from optarg */
        b_opt_arg = optarg;
        break;
    case ":":
        /* missing option argument 参数缺失*/
        fprintf(stderr, "%s: option "-%c" requires an argument
",
                argv[0], optopt);
        break;
    case "?":
    default:
        /* invalid option 非法选项*/
        fprintf(stderr, "%s: option "-%c" is invalid: ignored
",
                argv[0], optopt);
        break;
    }
}

相关变量

  • optind(option index): 数组下标,指向下一个未处理的参数。通过例子(摘自stackoverflow)能更好理解:
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    char optStr[] = "ab";
    int c;

    while ((c = getopt(argc, argv, optStr)) != -1) {
        printf("optind: %d
", optind);
        switch (c) {
            case "a":
                printf("-a
"); 
                break;
            case "b":
                printf("-b
"); 
                break;
            case "?":
                printf("error
");
                break;
          }
      }
    return 0;
}

测试结果:

$ ./a.out -ab  #例子1
optind: 1 
-a 
optind: 2
-b

$ ./a.out -a #例子2
optind: 2
-a

例子1:

#argv[]数据如下
argv[0]="./a.out"
argv[1]="-ab"
argv[2]=0

optind=1开始,处理完a,optind指向b所在位置,其实还是1;处理完b,指向下一个选项,即2

例子2:

#argv[]数据如下
argv[0]="./a.out"
argv[1]="-a"
argv[2]=0

optind=1开始,处理完a,指向下一个选项,即2

  • optarg: 如果合法选项带有参数,那么对应的参数,赋值给optarg

getopt_long()

根据函数名就可以知道getopt_long()用于处理长选项,如-help。函数声明如下:

#include <getopt.h>                                                
 
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex);

参数说明

前三个选项和getopt()完全相同,在此不再赘述。

  • longopts数组: 用于规定合法长选项以及长选项是否带参数(argument)。涉及到的option结构体声明如下
struct option {
    const char *name;
    int has_arg;
    int *flag;
    int val;
};
  1. name: 长选项的名称
  2. has_arg: 参数情况
符号常量 数值 Meaning
no_argument 0 无参数
required_argument 1 有参数
optional_argument 2 参数可选

考虑到“可读性”,一般使用“符号常量”

  1. int *flag: 如果flagNULL, getup_long() 返回val的值; 如果不是NULL, val的值赋给flag指针指向的内容,同时getopt_long()返回 0
  2. int val: flagNULL,val作为getopt_long()的返回值;如果flag不为NULL,val赋值给flag指针所指内容;
int *flag return value
NULL val
&name(<— val) 0

通过例子(摘自webbench)可加深理解

static const struct option long_options[]=
{
   {"force",no_argument,&force,1}, //-force 参数三(flag)不为NULL,force=1,getopt_long()返回0
   {"reload",no_argument,&force_reload,1},
   {"time",required_argument,NULL,"t"},
   {"help",no_argument,NULL,"?"},  //-help 第三个参数(flag)为NULL,直接返回 "?"
   {"http09",no_argument,NULL,"9"},
   {"http10",no_argument,NULL,"1"},
   {"http11",no_argument,NULL,"2"},
   {"get",no_argument,&method,METHOD_GET},
   {"head",no_argument,&method,METHOD_HEAD},
   {"options",no_argument,&method,METHOD_OPTIONS},
   {"trace",no_argument,&method,METHOD_TRACE},
   {"version",no_argument,NULL,"V"},
   {"proxy",required_argument,NULL,"p"},
   {"clients",required_argument,NULL,"c"},
   {NULL,0,NULL,0} //最后一个元素应该全为0
};

int main(int argc, char *argv[])
{
  int options_index=0;
  ...
  while((opt=getopt_long(argc,argv,"912Vfrt:p:c:?h",long_options,&options_index))!=EOF )
  {
    ...    
  }
}

注意: longopts数组最后一个元素应该全为0.

  • longindex: 一般设置为NULL; 如果不为NUll, 指向每次找到的长选项longopts的位置,可以通过该值(即索引)找到当前长选项的具体信息。

希望本文能帮助大家更好地理解getopt()getopt_long()。
更多的相关用法可以参考Linux Programming by Example: The Fundamentals

当前文章:http://tef490.hnibao.com/a/cfea6_139.html

发布时间:2017-10-18 00:02:11

我的心没有回程    我的心没有回程  我的心没有回程  我的心没有回程  我的心没有回程  我的心没有回程  我的心没有回程  我的心没有回程  我的心没有回程  

http://www.hnhx.net.cn/38B15WnjT3/201710100691.htmlhttp://www.hnhx.net.cn/9pb6Z8x13/201710100754.htmlhttp://www.hnhx.net.cn/F902t5Sp0/201710100139.htmlhttp://www.hnhx.net.cn/624c6F59C/201710100342.htmlhttp://www.hnhx.net.cn/Z94d696264/201710100927.htmlhttp://www.hnhx.net.cn/57Sp705pm3/201710100395.htmlhttp://www.hnhx.net.cnhttp://www.hnhx.net.cn/4047934051/201710100688.htmlhttp://www.hnhx.net.cn/0577n2486S/201710100281.htmlhttp://www.hnhx.net.cn/5B068958d/201710100369.htmlhttp://www.hnhx.net.cn/8Xf30982g9/201710100977.htmlhttp://www.hnhx.net.cn/Z94d696264/201710100927.htmlhttp://www.hnhx.net.cn/Q1sK9Y7WM5/201710100576.htmlhttp://www.hnhx.net.cn/543h2WG3x1/201710100090.htmlhttp://www.hnhx.net.cn/8210j97676/201710100705.htmlhttp://www.hnhx.net.cn/Z94d696264/201710100927.htmlhttp://www.hnhx.net.cn/n677167J21/201710100323.htmlhttp://www.hnhx.net.cn/38B15WnjT3/201710100691.htmlhttp://www.hnhx.net.cn/624c6F59C/201710100342.htmlhttp://www.hnhx.net.cn/F902t5Sp0/201710100139.htmlhttp://www.uknet.cnhttp://www.uknet.cnhttp://zatanzixun.cnhttp://www.hnhx.net.cn/Tm27D92fqG/201710100264.htmlhttp://www.hnhx.net.cnhttp://www.hnhx.net.cn/8210j97676/201710100705.htmlhttp://www.hnhx.net.cn/543h2WG3x1/201710100090.htmlhttp://www.hnhx.net.cn/8Xf30982g9/201710100977.htmlhttp://www.hnhx.net.cn/8210j97676/201710100705.htmlhttp://www.hnhx.net.cn/Z94d696264/201710100927.htmlhttp://www.hnhx.net.cn/9H75j7wB5d/201710100001.htmlhttp://www.hnhx.net.cn/57Sp705pm3/201710100395.htmlhttp://www.hnhx.net.cn/6x8Y2k0M54/201710100228.htmlhttp://www.hnhx.net.cn/g76wT1409/201710100295.htmlhttp://www.hnhx.net.cn/5B068958d/201710100369.htmlhttp://www.hnhx.net.cn/Q1sK9Y7WM5/201710100576.htmlhttp://www.hnhx.net.cn/9H75j7wB5d/201710100001.htmlhttp://www.hnhx.net.cn/4047934051/201710100688.htmlhttp://www.hnhx.net.cn/8Xf30982g9/201710100977.htmlhttp://www.hnhx.net.cn/F902t5Sp0/201710100139.htmlhttp://www.uknet.cnhttp://www.hnhx.net.cnhttp://www.hnhx.net.cn/n677167J21/201710100323.htmlhttp://www.hnhx.net.cn/Z94d696264/201710100927.htmlhttp://www.hnhx.net.cn/543h2WG3x1/201710100090.htmlhttp://www.uknet.cnhttp://www.hnhx.net.cn/0577n2486S/201710100281.htmlhttp://www.hnhx.net.cn/7734B06Z6/201710100809.htmlhttp://www.hnhx.net.cn/Z94d696264/201710100927.htmlhttp://www.hnhx.net.cn/5B068958d/201710100369.html