概述

命令行工具下的参数选项有两种,长选项和短选项。

getopt可以解析短选项,短选项以-开头,后面跟单个字母;

getopt_long可以解析长选项和短选项:长选项以--开头,后面可跟多个字母,短选项以-开头

getopt_long_only可以解析长选项和短选项:长选项以-或者--开头,后面可跟多个字母,短选项以-开头

执行时,可以是./test --opt xxx或者./test --opt=xxx

getopt

函数介绍

头文件:

    getopt.h

    unistd.h

函数原型:   

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

功能:       

    解析命令行短选项参数

参数:

argc:参数的个数(main)

argv:参数数组(main)

optstring:短选项字符集合,如 -i -n中的i,n

返回值:

若getopt找到短选项字符,则返回该选项字符;

若出现不能接受的选项字符或丢失选项参数,则返回?,同时optopt将被设置成相应选项字符;

如果所有命令行选项都解析完毕,返回 -1

    若选项后面有参数,则选项字符后加:, 对应的参数值保存在外部变量optarg中

如optstring 为"i:a",则表示程序支持两个短选项 -i arg和-a, -i后面须有参数值

当执行./a.out -i filename -a时,optarg指针就指向filename

    optstring中的指定的内容的意义(例如getopt(argc, argv, "ab:c:de::");)

1.单个字符,表示选项(如下例中的abcde各为一个选项)。

2.单个字符后接一个冒号:表示该选项后必须跟一个参数。参数紧跟在选项后或者以空格隔开。该参数的指针赋给optarg(如下例中的b:c:)。

3 单个字符后跟两个冒号,表示该选项后可以跟一个参数,也可以不跟。如果跟一个参数,参数必须紧跟在选项后不能以空格隔开。该参数的指针赋给optarg。(如上例中的e::,如果没有跟参数,则optarg = NULL)

几个外部变量(全局变量),可以直接用。

optarg:若短选项后有参数,则optarg指向该参数。char *类型

optind:扫描选项时,标识下一个选项的索引;扫描结束后,标识第一个非选项参数索引。int类型

opterr:出现不可识别的选项时,getopt将打印错误信息。将opterr设为0,可不打印错误信息。int类型

optopt:最后一个未知选项。int类型

解析过程

getopt首先扫描argv[1]到argv[argc-1],并将选项及参数依次放到argv数组的最左边,非选项参数依次放到argv的最后边

如执行程序为:

     0         1    2   3     4  5  6       7  8  9 

$ ./mygetopt file1 -i infile -a -o outfile -v -h file2

扫描过程中,optind是下一个选项的索引, 非选项参数将跳过,同时optind增1。

optind初始值为1。当扫描argv[1]时,为非选项参数,跳过,optind=2;

扫描到-i选项时,后面有参数,下一个将要扫描的选项是-a,则optind更改为4;

扫描到-a选项时,下一个选项是-o,optind=5;

扫描到-o选项时,后面有参数,下一个选项是-v,optind=7;

扫描到-v选项时,下一个选项是-h,optind=8;

扫描到-h选项时,optind=9

扫描结束后,getopt会将argv数组修改成下面的形式

     0       1   2     3  4     5    6  7   8    9

$./mygetopt -i infile -a -o outfile -v -h file1 file2

同时,optind会指向非选项的第一个参数,如上面,optind将指向file1

例程

1.while ((iError = getopt(argc, argv, "s:f:h:d:")) != -1)

{

    switch(iError)

    { case 's':

      {  

          dwFontSize = strtoul(optarg, NULL, 0);

          break;

      }

      case 'f':

      {  

          strncpy(acFreetypeFile, optarg, 128);

          acFreetypeFile[127] = '\0';

          break;  ....

2.

void usage(const char *p);  

int main(int argc, char *argv[])  

{

    int ch=0;  

    opterr=0; // prevent error information to print for unrecognized options  

    while( (ch=getopt(argc, argv, "i:ao:vh") ) != -1 )  

     {  

        switch(ch)  

        {  

           case 'i':  

                printf("option i: %s\n", optarg);  

                printf("optind=%d\n\n", optind);  

                break;  

           case 'a':  

                printf("option a :%c\n", ch);  

                printf("optind=%d\n\n", optind);  

                break;  

           case 'o':  

                printf("option o: %s\n", optarg);  

                printf("optind=%d\n\n", optind);  

                break;  

           case 'v':  

                printf("option v: %c\n", ch);  

                printf("optind=%d\n\n", optind);  

                break;  

           case 'h':  

                usage(argv[0]);  

                printf("optind=%d\n\n", optind);  

                break;  

           default:  

                printf("unrecognized option: %c\n", optopt);  

                usage(argv[0]);  

        }  

     }  

    if ( optind < argc )  

       {  

          printf("\nnon-option arguments below:\n");  

          while( optind < argc )  

            {  

                printf("%s\n", argv[optind++]);  

            }  

       }  

    return 0;  

}  

void usage(const char *p)  

{  

   printf("Usage: %s [-i infile] [-a] [-o outfile] [-v] [-h] [file]\n", p);  

执行结果:

$ ./mygetopt file1 -i infile -a -o outfile -v -h file2

option i: infile

optind=4

option a :a

optind=5

option o: outfile

optind=7

option v: v

optind=8

Usage: ./mygetopt [-i infile] [-a] [-o outfile] [-v] [-h] [file]

optind=9

non-option arguments below:

file1

file2    

getopt_long

函数介绍

功能:​   解析命令行长选项参数

头文件:

    getopt.h

    unistd.h

函数原型: ​  

    int getopt_long(int argc, char * const argv[],

                  const char *optstring,

                  const struct option *longopts, int *longindex);

参数:

argc:参数的个数(main)

argv:参数数组(main)

optstring:短选项字符集合,如 -i -n中的i,n

longopts:结构的实例

        struct option {

            const char *name; //name表示的是长参数名

            int has_arg; //has_arg有3个值:

                             // no_argument(或者是0),表示该参数后面不跟参数值

                             // required_argument(或者是1),表示该参数后面一定要跟参数值:--name Tom

                             // optional_argument(或者是2),表示该参数后参数可选:--name和--name Tom皆可。

            int *flag;        //用来决定,getopt_long()的返回值到底是什么。

                                  //null(通常情况),函数会返回与该项option匹配的val值;

                                  //不是NULL,val的值被赋到flag指向的整型数中,并且返回值设置为0。

            int val; //用于指定函数找到该选项时的返回值,或者当flag非空时指定flag指向的数据的值。

        }

longindex:当前长参数在longopts中的索引值

返回值:

取决于longopts的成员:flag

例程

程序

#include   

#include   

#include   

#include   

int  main(int argc, char **argv)  

{  

   int opt;  

   int digit_optind = 0;  

   int option_index = 0;  

   char *optstring = "a:b:c:d";  

   static struct option long_options[] = {  

       {"reqarg", required_argument, NULL, 'r'},  

       {"nonarg",  no_argument,       NULL, 'n'},  

       {"optarg", optional_argument, NULL, 'o'},  

       {0, 0, 0, 0}  

   };  

   while ( (opt = getopt_long(argc, argv, optstring, long_options, &option_index)) != -1)  

   {  

        printf("opt = %c\n", opt);  

        printf("optarg = %s\n", optarg);  

        printf("optind = %d\n", optind);  

        printf("argv[optind - 1] = %s\n",  argv[optind - 1]);  

        printf("option_index = %d\n", option_index);  

   }  

   return 0;  

}

运行结果:

1. ./test_getopt_long -a 100 --reqarg 100 --nonarg  

opt = a  

optarg = 100  

optind = 3  

argv[optind - 1] = 100  

option_index = 0  

opt = r  

optarg = 100  

optind = 5  

argv[optind - 1] = 100  

option_index = 0  

./test_getopt_long: unrecognized option '--nonarg'  

opt = ?  

optarg = (null)  

optind = 6  

argv[optind - 1] = --nonarg  

option_index = 0  

2. 所给的参数存在问题时,opt(即函数返回值是’?’),如:

./test_getopt_long -a  

./test_getopt_long: option requires an argument -- 'a'  

opt = ?  

optarg = (null)  

optind = 2  

argv[optind - 1] = -a  

option_index = 0  

./test_getopt_long --reqarg  

./test_getopt_long: option '--reqarg' requires an argument  

opt = ?  

optarg = (null)  

optind = 2  

argv[optind - 1] = --reqarg  

getopt_long_only

与getopt_long对比

相同点

        函数参数、参数含义,返回值都一样。

不同点

        getopt_long_only把’-’后的选项依然当做长选项,如果一个以’-’开头的选项没有在option数组中找到匹配的选项,但是在optstring中有匹配的短选项,则当成短选项处理。

例:以下两种是一样的

./test_getopt_long_only -a 100 --reqarg 100 --nonarg

./test_getopt_long_only -a 100 -reqarg 100 -nonarg

处理非法参数

在使用getopt或者getopt_long函数解析参数的时候,需要对非法参数进行处理,处理方法如下。 

    在while ((ret = getopt_long (...))!= -1 ) {}之后,写以下程序

    //提示用户输入的命令中含有无效字符,并列举出所有的无效字符

    if ( optind < argc ) 

    {

        fprintf ( stderr, "Invalid configuration information:");

        while ( optind < argc )

        {

            fprintf ( stderr, "%s ", argv[optind++]);

        }

        fprintf ( stderr, "\n");

        printf("please input\"./sd_test -h\" or \"./sd_test --help\" get some help information!\n ");

        return -1;

    }