argc,argv参数解析函数getopt(),getopt_long()介绍

命令选项参数解析

我们都是知道程序在启动时是可以接收命令参数的。通过main(int argc,char **argv)函数的argc和argv来传入命令参数。这时我们需要解析。当然glibc库中包含了相关函数来方便我们解析命令参数。

为了表述方便,我们用命令gcc -o exefile test.c来举例说明。其中gcc是运行命令(可执行文件),-o exefile test.c是它的参数。各个参数之间使用空格分开。main()函数的argc表明了输入参数的个数。此例的argc=4(gcc本身也算一个参数)。argv为一个字符串指针数组。存放这所有输入参数的指针。如argv[0]指向gcc,argv[1]指向-o,argv[2]指向exefile等等。

除此之外,输入参数中有些术语需要了解。如下

  1. 短选项:如上面的-o就是短选项。它由-开头,后面只能跟一个字符。短选项又具体分为:
    1. 必须带参数的短选项:指它后面必须要有一个参数。如-o exefile,exefile就是它的参数。
    2. 可选带参的短选项:指它后面可以带或不带参数。
    3. 不带参的短选项:指它后面不带参数。
  2. 长选项:如--version就是长选项。它由--开头,后面可跟多个字符。它也分必须带参,可选带参,不带参
  3. 无选项参数:它前面不需要有短选项长选项。如上面的test.c参数。

glibc库中提供了支持解析短选项的getopt()函数和长选项的getopt_long()函数。看下面的介绍和使用例程。

解析程序输入参数相关函数介绍

下面函数都需要包括getopt.h文件。

  1. int getopt(int argc, char *const argv[],const char *optstring)
    1. 描述:解析命令行参数。调用getopt()函数解析完argv数组后,会对其排序。将其无选项参数放在最后。如果不想让其排序,定义环境变量_POSIX_OPTION_ORDER即可。
    2. argc,argv:和main函数的这两个参数一样。第一个代表参数个数。第二个是选项数组。
    3. optstring:指定选项格式。具体格式如下(a代表某个选项)
      1. a:表示此选项没有参数,如-a。如果跟了参数会报错。如-a lkd这种格式错误。
      2. a::表示此选项有参数,如-a lkd。以可连写为-alkd。如果不跟参数会报错。
      3. a::表示此选项的参数可选。当有时必须用连写方式-alkd。此种格式是GNU扩展的。
      4. eg:optstring = "a:bc::"表示a选项必须要有参数,b选项无参数,c选项可有可无。所以输入参数的格式应为./test -a lkd -b -cname.
    4. return:如果选项成功找到,返回选项字母;当没有更多的选项参数可用时,它返回-1.
    5. 注意:对其无选项参数,可以在getopt()将选项参数解析完之后(此时会参数默认会自动排序,将其无选项参数放在了最后),直接使用optindargc对比打印。
    for(int i = optind; i < argc; i++){
        printf("argv[%d]:%s\n",i,argv[i]);
    }
  2. char *optarg全局变量
    1. 描述:getopt()会设置此变量。使其指向选项参数的值字符串。
  3. int optind全局变量
    1. 描述:argv数组中下一个要解析元素的索引(inxdex)。系统初始化时此值为1.调用者可以在使用过程中将它复位到1.
  4. int optopt全局变量
    1. 描述:当getopt()遇到未知的选项字符或缺少必需参数的选项时,它将该选项字符存储在该变量中。您可以使用它来提供您自己的诊断消息。
  5. int opterr全局变量
    1. 描述:当如果设置opterr!=0,那么当getopt()遇到一个未知的选项字符或一个缺少必需参数的选项时,将向标准错误流输出一条错误消息.这是默认的行为。如果设置opterr=0,getopt()不会打印任何消息,但它仍然返回字符?表示错误。

使用例程。命令行运行命令为./test xxx -a guo -b wei -c ddd

#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc,char **argv)
{
    int c;

    /* 打印原始的输入参数 */
    printf("argc:%d\n",argc);
    for(int i = 0; i < argc; i++){
        printf("argv[%d]:%s\n",i,argv[i]);
    }

    /* 解析选项参数并打印 */
    printf("------------------\n");
    while( (c = getopt(argc,argv,"a:b:c")) != -1){
        char *parg = (optarg == NULL ? "NULL" : optarg);
        printf("argv[%d]:-%c %s\n",optind-1,c,parg);
    }

    /* 打印无选项参数 */
    printf("------------------\n");
    for(int i = optind; i < argc; i++){
        printf("argv[%d]:%s\n",i,argv[i]);
    }

    /* 打印排序后的参数 */
    printf("------------------\n");
    printf("argc:%d\n",argc);
    for(int i = 0; i < argc; i++){
        printf("argv[%d]:%s\n",i,argv[i]);
    }
}

下面的这两个函数是GNU扩展的。用于支持长选项的解析。

  1. int getopt_long(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex)
    1. 描述:在getopt()函数的基础上怎加了长选项(如--version)的解析支持。如果程序只支持长选项,应让optstring=""
    2. longopts选项应该是一个struct option结构体数组指针。最后一个元素的所有成员要为0.此结构体如下:
    struct option {
        const char *name;    //长选项名称。
        int         has_arg; //有三种情况。no_argument:表明此选项不需要参数。required_argument表示必须要有参数。optional_argument表示参数可选。
        int        *flag;    //如果flag=NULL.那么函数返回val.否则返回0.*flag里保存val.
        int         val;函数返回或者*flag的值。
    };
    1. 再解释一下结构体中的flag和val.它俩是配合使用的。主要功能就是匹配短选项。比如某个命令的长选项--version和短选项-V的含义一样。那么就可以使val = V,flag=NULL那么getopt_long()的返回值就为短选项。处理方式变得和getopt()一模一样。
    2. longindex:它指向一个变量,该变量被设置为长选项相对于longopts的索引。
  2. getopt_long_only().
    1. 描述:功能类似getopt_long().只是 getopt_long 只将–name当作长参数,但 getopt_long_only 会将–name和-name两种选项都当作长参数来匹配。getopt_long_only如果选项-name不能在longopts中匹配,但能匹配一个短选项,它就会解析为短选项。

下面是一个使用例程:

#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc,char **argv)
{
    int longindex;
    struct option longopts[] = {
        {"version",no_argument,0,'V'},
        {0,0,0,0}
    };

    while(1){
        int c = getopt_long(argc,argv,"a:b:c",longopts, &longindex);

        if(c == -1){
            break;
        }

        char *parg = (optarg == NULL ? "NULL" : optarg);
        printf("-%c %s\n",c,parg);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

theboynoName

感谢鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值