解析命令行参数的函数

0.几个重要的全局变量与短选项和长选项的概念:

 extern char *optarg;
 extern int optind, opterr, optopt;

1.全局变量解释:
optarg:如果选项带参数,参数保存在optarg中。如果选项带可选参数,而实际无参数时,optarg为NULL。

optind:argv数组中下一次需要处理的元素的下标,系统默认初始化此值为1.0是没有意义的,argv[0]为程序名,在解析命令行参数中是没有意义的。getopt正常解析完毕后,optind设置为argv数组中第一个不是选项的元素的下标(一般为0)。

opterr:存储错误选项字符.

2.GNU/Linux的命令行选项有两种类型:短选项和长选项,前者以 '-' 作为前导符,后者以 '--' 作为前导符。-n表示是一个不带参数的短选项。--n表示是一个不带参数的长选项。现在有一个带有参数的短选项比如说-w foo,那么它和长选项--foo是等价的。

1.getopt函数:短选项解析函数

函数声明:

 #include 
 int getopt(int argc, char * const argv, const char *optstring);

函数参数:
1.argc:主函数传递过来的实参
2.argv:主函数传递过来的实参
3.optstring:一个包含选项字符的字符串。一组短选项组成的字符串

函数调用结果
1.该函数每解析完一个选项,就返回该选项字符。选项字符解析完毕后,调用getopt函数将会返回-1,然后optind设置为argv数组中第一个不是选项的元素的下标。
2.当调用getopt函数检测到错误时(比如说检测到的选项字符不在optstring实参中),默认情况下函数返回'?'。为什么说是默认呢?因为如果通过optstring实参指明选项带参数,而实际命令行没有参数时,getopt返回':'而不是'?'

关于optstring,还有几点说明:
1.如果选项带参数,该选项后接冒号,比如optstring这个实参值为"a:b",指示a带参数,b没有参数;

2.如果选项带可选参数,该选项后接两个冒号,比如"a::b",表明a可能有参数,也可能没有;

3.如果optstring的开头字符为':',表明如果指明选项带参数,而实际命令行没有参数时,getopt返回':'而不是'?'(默认情况下返回'?',和无法识别的参数返回一样);

4.如果optstring的开头字符为'+',表明一但遇到一个非选项参数,马上停止扫描,随后的部分当作参数来解释;

5.如果optstring的开头字符为'-',表明如果遇到无选项参数,则把它当作选项1(不是字符'1')的参数

示例:(来源于man文档)

 #include 
  3        #include 
  4        #include 
  5 
  6        int
  7        main(int argc, char *argv[])
  8        {
  9            int flags, opt;
 10            int nsecs, tfnd;
 11 
 12            nsecs = 0;
 13            tfnd = 0;
 14            flags = 0;
 15            //因为短选项解析完毕后getopt函数返回-1,所以作为循环退出的条件
 16            //optstring这个实参的值为"nt:",意思是说n这个选项不带参数,t这个选项带有一个参数
 17            while ((opt = getopt(argc, argv, "nt:")) != -1) {
 18                switch (opt) {
 19                case 'n':
 20                    flags = 1;
 21                    break;
 22                case 't':
 23                    nsecs = atoi(optarg);
 24                    tfnd = 1;
 25                    break;
 26                default: /* '?' */
 27                    fprintf(stderr, "Usage: %s [-t nsecs] [-n] name\n",
 28                            argv[0]);
 29                    exit(EXIT_FAILURE);
 30                }
 31            }
 32 
 33            printf("flags=%d; tfnd=%d; nsecs=%d; optind=%d,argc=%d\n",
 34                    flags, tfnd, nsecs, optind,argc);
 35             //optind这个全局变量默认初始化为1,不指定命令行参数argc就为1
 36            if (optind >= argc) {
 37                fprintf(stderr, "Expected argument after options\n");
 38                exit(EXIT_FAILURE);
 39            }
 40             //如果函数解析完毕,那么optind的值重置为argv数组中第一个不是选项的元素的下标
 41             //比如说./a.out -n 5 -t 100这样
 42             printf("name argument = %s\n", argv[optind]);
 43 
 44            /* Other code omitted */
 45 
 46            exit(EXIT_SUCCESS);
 47        }                  

运行示例:

zhihua@zy:~/sysFuncPrac$ ./a.out -n 5 -t 100
flags=1; tfnd=1; nsecs=100; optind=4,argc=5
name argument = 5

3.getopt_long函数:解析长选项或者短选项函数

函数声明:

 #include   //for option struct

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

函数参数:
longops:指向一个option结构体数组的第一个元素。
longindex:getopt_long的最后一个参数longindex在函数返回时指向被搜索到的选项在longopts数组中的下标。

关于option struct如下:

struct option {
//长选项名
               const char *name;  
//has_arg:如果选项不带有参数则实参可以是no_argument,即为0;
//如果选项要求一个参数,则实参可以是required_argument,即为1;
//如果选项可以有一个可选参数,也可以不用,则实参可以是optional_argument,即为2.
               int         has_arg;  
//flag:如果flag为null,则getopt_long函数返回val的值;flag
//不为null,则指向一个变量,变量的值为val,并且函数返回0.
               int        *flag;
//val:getopt_long函数返回的值;或者是flag指向的变量的值
               int         val;
           };

注意在初始化option struct时:The last element of the array has to be filled with zeros.

函数返回值:
1.如果flag这个实参为null,那么这个函数返回val的值。这样短选项字符解析和长选项解析搭建了桥梁。
2.如果flag这个实参不为null,那么这个函数返回0
3.选项字符解析完毕后,调用getopt_long函数将会返回-1
4.当调用getopt_long函数检测到错误时(比如说检测到的选项字符不在longops实参中),默认情况下函数返回'?'

示例:(来源于man 文档)

1 #include        /*  for  printf  */  
  2 #include      /* for exit */ 
  3 
  4 #include      /*for option struct */
  5 
  6 int main(int argc, char **argv) {
  7     int c;
  8     int digit_optind = 0;
  9 
 10     while (1) {
 11         int this_option_optind = optind ? optind : 1;
 12         int option_index = 0;
 13         static struct option long_options[] = {
 14             {"add",     required_argument, 0,  0 },
 15             {"append",  no_argument,       0,  0 },
 16             {"delete",  required_argument, 0,  0 },
 17             {"verbose", no_argument,       0,  0 },
 18             {"create",  required_argument, 0, 'c'},
 19             {"file",    required_argument, 0,  0 },
 20             {0,         0,                 0,  0 }  //option结构体数组的最后一个元素必须以0填充
 21         };
 22 
 23         //第三个实参表明这个函数也支持短选项
 24         c = getopt_long(argc, argv, "abc:d:012",
 25                 long_options, &option_index);
 26         if (c == -1)    //当解析完毕后或者并未指定命令行参数才跳出循环
 27             break;
 28 
 29         switch (c) {
 30             case 0:
 31                 //option_index存有当前匹配到的选项在option结构体数组中的下标
 32                 printf("option %s", long_options[option_index].name);
 33                 //optarg:如果选项带参数,参数保存在optarg中。如果选项带可选参数,而实际无
 34                 //参数时,optarg为NULL。
 35                 if (optarg)
 36                     printf(" with arg %s", optarg);
 37                 printf("\n");
 38                 break;
 39 
 40             case '0':
 41             case '1':
 42             case '2':
 43                 if (digit_optind != 0 && digit_optind != this_option_optind)
 44                     printf("digits occur in two different argv-elements.\n");
 23         //第三个实参表明这个函数也支持短选项
 24         c = getopt_long(argc, argv, "abc:d:012",
 25                 long_options, &option_index);
 26         if (c == -1)    //当解析完毕后或者并未指定命令行参数才跳出循环
 27             break;
 28 
 29         switch (c) {
 30             case 0:
 31                 //option_index存有当前匹配到的选项在option结构体数组中的下标
 32                 printf("option %s", long_options[option_index].name);
 33                 //optarg:如果选项带参数,参数保存在optarg中。如果选项带可选参数,而实际无
 34                 //参数时,optarg为NULL。
 35                 if (optarg)
 36                     printf(" with arg %s", optarg);
 37                 printf("\n");
 38                 break;
 39 
 40             case '0':
 41             case '1':
 42             case '2':
 43                 if (digit_optind != 0 && digit_optind != this_option_optind)
 44                     printf("digits occur in two different argv-elements.\n");
 45                 digit_optind = this_option_optind;
 46                 printf("option %c\n", c);
 47                 break;
 48 
 49             case 'a':
 50                 printf("option a\n");
 51                 break;
 52 
 53             case 'b':
 54                 printf("option b\n");
 55                 break;
 56 
 57             case 'c':
 58                 printf("option c with value '%s'\n", optarg);
 59                 break;
 60 
 61             case 'd':
 62                 printf("option d with value '%s'\n", optarg);
 63                 break;
 64 
 65             case '?':
 66                 break;
 67 
 68             default:
 69                 printf("?? getopt returned character code 0%o ??\n", c);
 70         }
 71     }
 72 
 73     if (optind < argc) {
 74         printf("non-option ARGV-elements: ");
 75         while (optind < argc)
 76             printf("%s ", argv[optind++]);
 77         printf("\n");
 78     }
 79 
 80     exit(EXIT_SUCCESS); 
 81 }

运行示例如下:


zhihua@zy:~/sysFuncPrac$ ./a.out --append --add 100 -d 200 -2
option append
option add with arg 100
option d with value '200'
option 2
zhihua@zy:~/sysFuncPrac$ ./a.out --create 
./a.out: option '--create' requires an argument
zhihua@zy:~/sysFuncPrac$ ./a.out --create 300 -c
option c with value '300'
./a.out: option requires an argument -- 'c'

4.getopt_long_only函数:

getopt_long_only类似于getopt_long,但是它把'-'开头的选项当作长选项来处理。如果该选项与长选项不匹配,而与短选项匹配,则可以作为短选项解析。

你可能感兴趣的:(解析命令行参数的函数)