免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1027 | 回复: 0
打印 上一主题 下一主题

getopt_long()函数解析 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-19 16:08 |只看该作者 |倒序浏览
20 世纪 90 年代,UNIX 应用程序开始支持长选项,即一对短横线、一个描述性选项名称,还可以包含一个使用等号连接到选项的参数。
GNU提供了getopt-long()和getopt-long-only()函数支持长选项的命令行解析,其中,后者的长选项字串是以一个短横线开始的,而非一对短横线。
getopt_long() 是同时支持长选项和短选项的 getopt() 版本。下面是它们的声明:
   
        
            #i nclude
            
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);
        
   
getopt_long
()的前三个参数与上面的getopt()相同,第4个参数是指向option结构的数组,option结构被称为“长选项表”。longindex参数
如果没有设置为NULL,那么它就指向一个变量,这个变量会被赋值为寻找到的长选项在longopts中的索引值,这可以用于错误诊断。
option结构在getopt.h中的声明如下:
   
        
            struct option{
                  const char *name;
                  int has_arg;
                  int *flag;
                  int val;
            };
        
   
对结构中的各元素解释如下:
const char *name
这是选项名,前面没有短横线。譬如"help"、"verbose"之类。
int has_arg
描述了选项是否有选项参数。如果有,是哪种类型的参数,此时,它的值一定是下表中的一个。
   
        
            符号常量
            数值
            含义
        
        
            no_argument
            0
            选项没有参数
        
        
            required_argument
            1
            选项需要参数
        
        
            optional_argument
            2
            选项参数可选
        
   
int *flag
如果这个指针为NULL,那么getopt_long()返回该结构val字段中的数
值。如果该指针不为NULL,getopt_long()会使得它所指向的变量中填入val字段中的数值,并且getopt_long()返回0。如果
flag不是NULL,但未发现长选项,那么它所指向的变量的数值不变。
int val
这个值是发现了长选项时的返回值,或者flag不是NULL时载入*flag中的值。
典型情况下,若flag不是NULL,那么val是个真/假值,譬如1
或0;另一方面,如果flag是NULL,那么val通常是字符常量,若长选项与短选项一致,那么该字符常量应该与optstring中出现的这个选项的
参数相同。
每个长选项在长选项表中都有一个单独条目,该条目里需要填入正确的数值。数组中最后的元素的值应该全是0。数组不需要排序,getopt_long()会进行线性搜索。但是,根据长名字来排序会使程序员读起来更容易。
以上所说的flag和val的用法看上去有点混乱,但它们很有实用价值,因此有必要搞透彻了。
大部分时候,程序员会根据getopt_long()发现的选项,在选项处理过程中要设置一些标记变量,譬如在使用getopt()时,经常做出如下的程序格式:
   
        
            int do_name, do_gf_name, do_love; /*标记变量*/
            char *b_opt_arg;
            
            while((c = getopt(argc, argv, ":ngl:")) != -1)
            {
                  switch (c){
                  case 'n':
                      do_name = 1;
                  case 'g':
                      do_gf_name = 1;
                      break;
                      break;
                  case 'l':
                      b_opt_arg = optarg;
                  ……
                  }
            }
        
   
当flag
不为NULL时,getopt_long*()会为你设置标记变量。也就是说上面的代码中,关于选项'n'、'l'的处理,只是设置一些标记,如果
flag不为NULL,时,getopt_long()可以自动为各选项所对应的标记变量设置标记,这样就能够将上面的switch语句中的两种种情况减
少到了一种。下面给出一个长选项表以及相应处理代码的例子。
清单5:
   
        
            #i nclude
            #i nclude
            
            int do_name, do_gf_name;
            char *l_opt_arg;
            
            struct option longopts[] = {
                  { "name",          no_argument,              &do_name,          1      },
                  { "gf_name",      no_argument,              &do_gf_name,      1      },
                  { "love",          required_argument,      NULL,                  'l'      },
                  {       0,      0,      0,      0},
            };
            
            int main(int argc, char *argv[])
            {
                  int c;
               
                  while((c = getopt_long(argc, argv, ":l:", longopts, NULL)) != -1){
                      switch (c){
                      case 'l':
                          l_opt_arg = optarg;
                          printf("Our love is %s!\n", l_opt_arg);
                          break;
                      case 0:
                          printf("getopt_long()设置变量 : do_name = %d\n", do_name);
                          printf("getopt_long()设置变量 : do_gf_name = %d\n", do_gf_name);
                          break;
                      }
                  }
                  return 0;
            }
        
   
在进行测试之前,再来回顾一下有关option结构中的指针flag的说明吧。
   
        
            如
果这个指针为NULL,那么getopt_long()返回该结构val字段中的数值。如果该指针不为NULL,getopt_long()会使得它所指
向的变量中填入val字段中的数值,并且getopt_long()返回0。如果flag不是NULL,但未发现长选项,那么它所指向的变量的数值不变。
        
   
下面测试一下:
   
        
            $ ./long_opt_demo --name
            getopt_long()设置变量 : do_name = 1
            getopt_long()设置变量 : do_gf_name = 0
            
            $ ./long_opt_demo --gf_name
            getopt_long()设置变量 : do_name = 0
            getopt_long()设置变量 : do_gf_name = 1
            
            $ ./long_opt_demo --love forever
            Our love is forever!
            
            $ ./long_opt_demo -l forever
            Our love is forever!
        
   
测试过后,应该有所感触了。关于flag和val的讨论到此为止。下面总结一下get_long()的各种返回值的含义:
   
        
            返回值   
            含 义
        
        
            0      
            getopt_long()设置一个标志,它的值与option结构中的val字段的值一样
        
        
            1
            每碰到一个命令行参数,optarg都会记录它
        
        
            '?'
            无效选项
        
        
            ':'
            缺少选项参数
        
        
            'x'
            选项字符'x'
        
        
            -1
            选项解析结束
        
   
从实用的角度来说,我们更期望每个长选项都对应一个短选项,这种情况下,在option结构中,只要将flag设置为NULL,并将val设置为长选项所对应的短选项字符即可。譬如上面清单5中的程序,修改如下。
清单6:
   
        
            #i nclude
            #i nclude
            
            int do_name, do_gf_name;
            char *l_opt_arg;
            
            struct option longopts[] = {
                  { "name",          no_argument,              NULL,                  'n'      },
                  { "gf_name",      no_argument,              NULL,                  'g'      },
                  { "love",          required_argument,      NULL,                  'l'      },
                  {       0,      0,      0,      0},
            };
            
            int main(int argc, char *argv[])
            {
                  int c;
               
                  while((c = getopt_long(argc, argv, ":l:", longopts, NULL)) != -1){
                      switch (c){
                      case 'n':
                          printf("My name is LYR.\n");
                          break;
                      case 'g':
                          printf("Her name is BX.\n");
                          break;
                      case 'l':
                          l_opt_arg = optarg;
                          printf("Our love is %s!\n", l_opt_arg);
                          break;
                      }
                  }
                  return 0;
            }
        
   
测试结果如下:
   
        
            $ ./long_opt_demo --name --gf_name --love forever
            My name is LYR.
            Her name is BX.
            Our love is forever!
            
            $ ./long_opt_demo -ng -l forever
            My name is LYR.
            Her name is BX.
            Our love is forever!
        
   
9、在LINUX之外的系统平台上使用GNU getopt()或getopt_long()
只要从GNU程序或GNU C
Library(GLIBC)的CVS档案文件中copy源文件即可(http://sourceware.org/glibc/)。所需源文件是
getopt.h、getopt.c和getoptl.c,将这些文件包含在你的项目中。另外,你的项目中最好也将COPYING.LIB文件包含进去,
因为GNU LGPL(GNU 程序库公共许可证)的内容全部包括在命名为COPYING.LIB 的文件中。
10、结论
程序需要能够快速处理各个选项和参数,且要求不会浪费开发人员的太多时间。在这一点上,无论是GUI(图形用户交互)程序还是CUI(命令行交互)程序,
都是其首要任务,其区别仅在于实现方式的不同。GUI通过菜单、对话框之类的图形控件来完成交互,而CUI使用了纯文本的交互方式。在程序开发中,许多测
试程序用CUI来完成是首选方案。
getopt() 函数是一个标准库调用,可允许您使用直接的 while/switch 语句方便地逐个处理命令行参数和检测选项(带或不带附加的参数)。与其类似的 getopt_long() 允许在几乎不进行额外工作的情况下处理更具描述性的长选项,这非常受开发人员的欢迎。
文章出处:http://hi.baidu.com/xiao1dian/blog/item/acc1eccacf99b745f21fe7ed.html
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/64851/showart_1868762.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP