• getopt_long函数解析命令行参数


    转载:http://blog.csdn.net/hcx25909/article/details/7388750

    每一天你都在使用大量的命令行程序,是不是感觉那些命令行参数用起来比较方便,他们都是使用getopt来实现的。

    在Linux下使用getopt写程序是一种比较cool的事情,下面来简单的介绍一下getopt的使用。

    === getopt使用 ===

    在讨论参数处理之前,我们先明确两个概念:选项、选项参数
    gcc -g -o test test.c
    我们经常使用上面的命令来编译程序,这里g和o就是选项,其中test就是o的选项参数

    下面我们来看一下getopt:

    首先是函数声明:

    1 #include <unistd.h>
    2 extern char *optarg;
    3 extern int optind;
    4 extern int optopt;
    5 extern int opterr;
    6 extern int optreset;
    7 int getopt(int argc, char * const *argv, const char *optstring);

    直接看一个例子:

     1 /* getopt.c */
     2 #include <unistd.h>
     3 #include <stdio.h>
     4 int main(int argc, char * argv[])
     5 {
     6     int aflag=0, bflag=0, cflag=0;
     7     int ch;
     8     while ((ch = getopt(argc, argv, "ab:c")) != -1)
     9     {
    10         printf("optind: %d
    ", optind);
    11         switch (ch) {
    12         case 'a':
    13             printf("HAVE option: -a
    ");
    14             aflag = 1;
    15             break;
    16         case 'b':
    17             printf("HAVE option: -b
    ");
    18             bflag = 1;
    19             printf("The argument of -b is %s
    ", optarg);
    20             break;
    21         case 'c':
    22             printf("HAVE option: -c");
    23             cflag = 1;
    24             break;
    25         case '?':
    26             printf("Unknown option: %c
    ",(char)optopt);
    27             break;
    28         }
    29     }
    30 }

    通过上面的例子,大家应该可以照猫画虎,就可以在自己的程序中使用getopt函数了。

    getopt()每调用一次返回一个选项。
    argc 和 argv 很显然就是 main 函数的两个参数。
    字符串 optstring 可以包含下列元素:单个字符,字符后面接一个冒号说明后面跟随一个选项参数,字符后面接两个冒号说明后面跟随一个可有可无的选项参数。例如,一个选项字符 "x" 表示选项 "-x" ,选项字符 "x:" 表示选项和其参数 "-x argument",选项字符 "x::" 表示选项 x 的参数是可选的(“::” 是 GNU 增加的,不一定在所有的UNIX 系统下都可以使用)。
    getopt()的返回后,如果有选项参数的话 optarg 指向选项参数,并且变量 optind 包含下一个 argv 参数作为对 getopt() 下一次调用的索引。变量 optopt 保存最后一个由 getopt() 返回的已知的选项。
    当参数列已经到结尾时getopt()函数返回-1,当遇到一个未知的选项时 getopt 返回'?'。参数列中选项的解释可能会被'--'取消,由于它引起 getopt()给参数处理发送结束信号并返回-1。

    很多时候,我们不希望输出任何错误信息,或更希望输出自己定义的错误信息。可以采用以下两种方法来更改getopt()函数的出错信息输出行为:
    在调用getopt()之前,将opterr设置为0,这样就可以在getopt()函数发现错误的时候强制它不输出任何消息。
    如果optstring参数的第一个字符是冒号,那么getopt()函数就会保持沉默,并根据错误情况返回不同字符,如下:
    “无效选项” ―― getopt()返回'?',并且optopt包含了无效选项字符(这是正常的行为)。
    “缺少选项参数” ―― getopt()返回':',如果optstring的第一个字符不是冒号,那么getopt()返回'?',这会使得这种情况不能与无效选项的情况区分开。
    例如optstring为:a:b::c,表示a带一个参数,b可选,c不带参数
    如果输入d,“无效选项“,getopt返回'?'
    如果输入的a忘记带参数,“缺少选项参数”,getopt应返':' ;如果不再optstring的第一个字符不是':'的话,那么将会把这个错当成"无效参数",从而getopt返回'?';从而无法区别错误类型

    比如:
    wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt -a -d -b foo
    optind: 2
    HAVE option: -a
    ./getopt: invalid option -- d
    optind: 3
    Unknown option: d
    optind: 5
    HAVE option: -b
    The argument of -b is foo
    wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt -a -- -c -b foo
    optind: 2
    HAVE option: -a

    getopt 的源代码在下面,getopt 将只会解释到 -a。

    变量opterr和optind都被初始化为1。如果想要略去命令行的前几个参数,可以在调用getopt()前将optind设成其他值。
    如果不希望getopt()输出出错信息,将全域变量 opterr 设为 0 即可。

    是不是使用比较简单啊!

    === getopt_long使用 ===

    我敢说,几乎每个人在接触到一个新的命令的时候,第一件干的事情就是 cmd -h 或者是 cmd --help,-h我们都知道是使用getopt来实现的,那么--help是怎么实现的呢?那就是getopt_long了,他可以支持长参数

    先看一个例子程序:

     1 #include <stdio.h>
     2 #include <getopt.h>
     3 
     4 int do_name, do_gf_name;
     5 char *l_opt_arg;
     6 
     7 static const char *shortopts = "l:ng";
     8 struct option longopts[] = {
     9 {"name", no_argument, NULL, 'n'},
    10 {"gf_name", no_argument, NULL, 'g'},
    11 {"love", required_argument, NULL, 'l'},
    12 {0, 0, 0, 0},
    13 };
    14 
    15 int main (int argc, char *argv[])
    16 {
    17 int c;
    18 
    19 while ((c = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1)
    20     {
    21       switch (c)
    22    {
    23    case 'n':
    24       printf ("My name is LYR.
    ");
    25       break;
    26    case 'g':
    27       printf ("Her name is BX.
    ");
    28       break;
    29    case 'l':
    30       l_opt_arg = optarg;
    31       printf ("Our love is %s!
    ", l_opt_arg);
    32       break;
    33    }
    34     }
    35 return 0;
    36 }

    代码中我们使用getopt_long来实现长选项的解析,其中我们使用了一个结构体struct options的数组,struct options longopt[].
    struct options的定义如下:

    1 struct option{
    2      const char *name;
    3      int has_arg;
    4      int *flag;
    5      int val;
    6 };

    对结构中的各元素解释如下:
        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()会进行线性搜索。但是,根据长名字来排序会使程序员读起来更容易。

    下面,我们看一下程序中的这个结构:

    1 struct option longopts[] = {
    2 {"name", no_argument, NULL, 'n'},
    3 {"gf_name", no_argument, NULL, 'g'},
    4 {"love", required_argument, NULL, 'l'},
    5 {0, 0, 0, 0},
    6 };

    结构说明了三个常选项,name、gf_name、love三个选项,其中love需要选项;它们分别对应的短选项是n、g、l。
    注意:上面结构体数组中的结构体的第三个参数flag都为NULL.

    程序运行结果:
    wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt_long --name
    My name is LYR.
    wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt_long -n
    My name is LYR.
    wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt_long -l me
    Our love is me!
    wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt_long --love me
    Our love is me!
    wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ 


    === Reference ===
    GNU提供的getopt()函数的特点
    http://blog.csdn.net/realduke2000/archive/2007/10/05/1812126.aspx
    使用 getopt() 进行命令行处理
    http://www.ibm.com/developerworks/cn/aix/library/au-unix-getopt.html

    === Questions ===
    1、如何在getopt中指定可选参数
    2、能否实现使用一个选项带多个参数,例如 scanner -i 1.1.1.1 2.2.2.2 3.3.3.3

  • 相关阅读:
    轻松实现内容的无缝平滑滚动
    世界“新七大奇迹”揭晓 中国长城成功入选
    Blog_Backup:绿色博客备份工具
    【Vista中系统准备工具存在隐患,自动清除用户资料】
    Oracle大连全球支持中心运营就在我们公司前面!
    ASP.NET2.0下使用AJAX调用Webservice的方法
    配合AJAX天气预报的WebService
    Google兑现承诺你可以从google上删除你的搜索记录了
    全体注意:@live.com 形势不妙,可能三周内被收回
    国内软件联盟抨击微软以非正规手段推文档标准
  • 原文地址:https://www.cnblogs.com/3me-linux/p/4765632.html
Copyright © 2020-2023  润新知