打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
getopt

getopt_long()函数使用  

2010-05-23 04:58:39|  分类: 毕业论文 |字号 订阅

20 世纪 90 年代,UNIX 应用程序开始支持长选项,即一对短横线、一个描述性选项名称,还可以包含一个使用等号连接到选项的参数。

GNU提供了getopt-long()和getopt-long-only()函数支持长选项的命令行解析,其中,后者的长选项字串是以一个短横线开始的,而非一对短横线。

getopt_long() 是同时支持长选项和短选项的 getopt() 版本。下面是它们的声明:

#i nclude <getopt.h>

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_argument0选项没有参数
required_argument1选项需要参数
optional_argument2选项参数可选

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的用法看上去有点混乱,但它们很有实用价值,因此有必要搞透彻了。


— Variable: int opterr
If the value of this variable is nonzero, then getopt prints an error message to the standard error stream if it encounters an unknown option character or an option with a missing required argument. This is the default behavior. If you set this variable to zero, getopt does not print any messages, but it still returns the character ? to indicate an error.

— Variable: int optopt
When getopt encounters an unknown option character or an option with a missing required argument, it stores that option character in this variable. You can use this for providing your own diagnostic messages.

— Variable: int optind
This variable is set by getopt to the index of the next element of the argv array to be processed. Once getopt has found all of the option arguments, you can use this variable to determine where the remaining non-option arguments begin. The initial value of this variable is 1.

— Variable: char * optarg
This variable is set by getopt to point at the value of the option argument, for those options that accept arguments.


If getopt finds an option character in argv that was not included in options, or a missing option argument, it returns ‘?’ and sets the external variable optopt to the actual option character. If the first character of options is a colon (‘:’), then getopt returns ‘:’ instead of ‘?’ to indicate a missing option argument. In addition, if the external variable opterr is nonzero (which is the default), getopt prints an error message.


大部分时候,程序员会根据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 <stdio.h>
#i nclude <getopt.h>

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, "ngl:", 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 <stdio.h>
#i nclude <getopt.h>

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, "ngl:", 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通过菜单、对话框之类的图形控件来完成
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
getopt终端控制函数
Linux程序设计——用getopt处理命令行参数
getopt函数的使用
Linux环境(一)--程序参数
Windows下使用GetOpt函数使用
Linux编程里getopt_long_only函数用法详解
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服