解析命令行参数

CLI(Command Line Interface)编程中很重要的一步,就是命令行参数的解析。对于初涉这一块的兄弟来说,argv, argc摆弄起来还是非常繁琐的。本文简单的介绍getopt相关几个命令行参数解析函数的用法,并搭上几个简单的实例,力求使读者能够基本掌握它的用法。

 
  下面的几个API是从man 3 getopt中截取并简化。
 
  这个函数初定义在unistd.h中,实现最基本的命令行参数解析功能,只支持象-a -d这样短参数格式,不支持象--color --dir这样的长参数格式。
      int getopt(int argc, char * const argv[],
                  const char *optstring);
 
  这个函数定义在getopt.h中,实现了长短参数混合解析。
      int getopt_long(int argc, char * const argv[],
                  const char *optstring,
                  const struct option *longopts, int *longindex);
 
  这个函数定义在getopt.h中,只支持长参数的解析。
      int getopt_long_only(int argc, char * const argv[],
                  const char *optstring,
                  const struct option *longopts, int *longindex);
 
  在现实运用中,当然是中间一个函数用得最多,谁不想自己的CLI程序支持短参数的同时也支持长参数呢?
 
   短参数的定义:
  getopt使用optstring所指的字串作为短参数列表,象"1ac:d::"就是一个短参数列表。短参数的定义是一个'-'后面跟一个字母或数字,象-a, -b就是一个短参数。每个数字或字母定义一个参数。
 
  其中短参数在getopt定义里分为三种:
  1. 不带值的参数,它的定义即是参数本身
  2. 必须带值的参数,它的定义是在参数本身后面再加一个冒号
  3. 可选值的参数,它的定义是在参数本身后面加两个冒号
 
  在这里拿上面的"1ac:d::"作为样例进行说明,其中的1,a就是不带值的参数,c是必须带值的参数,d是可选值的参数。
  在实际调用中,'-1 -a -c cvalue -d', '-1 -a -c cvalue -ddvalue', '-1a -ddvalue -c cvalue'都是合法的。这里需要注意三点:
  1. 不带值的参数可以连写,象1和a是不带值的参数,它们可以-1 -a分开写,也可以-1a或-a1连写。
  2. 参数不分先后顺序,'-1a -c cvalue -ddvalue'和'-d -c cvalue -a1'的解析结果是一样的
  3. 要注意可选值的参数的值与参数之间不能有空格,必须写成-ddvalue这样的格式,如果写成-d dvalue这样的格式就会解析错误。
 
   getopt()的返回值:
  getopt()每次调用会逐次返回命令行传入的参数
  当没有参数的最后的一次调用时,getopt()将返回-1。
  当解析到一个不在optstring里面的参数,或者一个必选值参数不带值时,返回'?'
  当optstring是以':'开头时,缺值参数的情况下会返回':',而不是'?'
 
   getopt()的出错信息:
  使用getopt的时候,当参数有错的时候会经常出现一些我们不希望出现的出错信息。这是getopt通过stderr输出的错误信息。我们可以通过把opterr设成0来解决这个问题。
 
   参数值的获取:
  当参数后面带有值时,调用后会把值放入到optarg字符串里面;如果没有值时,这个字串将被置空。
 
  getopt()的三种解析模式:
  1. 默认情况下,getopt()会按照optstring定义的顺序进行参数解析,不在optstring定义的参数会返回?,然后把非参数的值放到argv队列的最后。
  2. 当optstring以'+'开头定义时,getopt()会跳过所有不在optstring中的参数,并把他们都当作是非参数的值发到队列的最后。
  3. 当optstring以'-'开头定义时,没看懂。。。。有空再看
 
   例1:用getopt()实现短参数的解析。
 
#include <stdio.h>
#include <unistd.h>
void parse_arg(int argc, char *argv[])
{
    int c;
    opterr = 0;
    while(1)
    {
        c = getopt_long (argc, argv, ":1ac:d::");
        if (c == -1)
        {
            break;
        }
        switch(c)
        {
            case '1':
            case 'a':
                printf ("option %c/n", c);
                break;
            case 'c':
                printf ("option c with value `%s'/n", optarg);
                break;
            case 'd':
                if (optarg != NULL)
                {
                    printf ("option d with value `%s'/n", optarg);
                }
                else
                {
                    printf ("option d/n");
                }
                break;
            case '?':
                printf("unknown parameter: %c/n", optopt);
                break;
            case ':':
                printf("need parameter: %c/n", optopt);
                break;
            default:
                printf ("?? getopt returned character code 0%o ??/n", c);
                break;
        }
    }
    if (optind < argc)
    {
        printf ("non-option ARGV-elements: ");
        while (optind < argc)
        {
            printf ("%s ", argv[optind++]);
        }
        printf ("/n");
    }
}

int main(int argc, char *argv[])
{
    parse_arg(argc, argv);
    return 0;
}
 
  例2:用getopt_long()实现长短参数的混合解析。
 
   不足之处:
 
  getopt没有提供强制参数或可选参数列表的功能,只是提出了一种参数获取的方法。在实际使用中,在使用getopt解析参数过后,还必须对程序的参数进行存在性,或有效性验证,这仍然是一件很繁琐的事情。期待在以后的应用中能够很好的解决这个问题。
 
  最后,getopt只是用一种既定的模式来进行了命令行参数的解析。既然是一种既定的模式,肯定就有它的缺陷。如果读者在实际运用中遇到一些getopt不能解决的地方,还是只有自己写方法来解析命令行参数。也许有朝一日会有一个比getopt更完美的命令行解析库出现
-------------------------------------------
 /*   STRTOK.C:   In   this   program,   a   loop   uses   strtok  
    *   to   print   all   the   tokens   (separated   by   commas  
    *   or   blanks)   in   the   string   named   "string".  
    */  
   
  #include   <string.h>  
  #include   <stdio.h>  
   
  char   string[]   =   "A   string/tof   ,,tokens/nand   some     more   tokens";  
  char   seps[]       =   "   ,/t/n";  
  char   *token;  
   
  void   main(   void   )  
  {  
        printf(   "%s/n/nTokens:/n",   string   );  
        /*   Establish   string   and   get   the   first   token:   */  
        token   =   strtok(   string,   seps   );  
        while(   token   !=   NULL   )  
        {  
              /*   While   there   are   tokens   in   "string"   */  
              printf(   "   %s/n",   token   );  
              /*   Get   next   token:   */  
              token   =   strtok(   NULL,   seps   );  
        }  
  }  
  Output  
   
  A   string       of   ,,tokens  
  and   some     more   tokens  
   
  Tokens:  
    A  
    string  
    of  
    tokens  
    and  
    some  
    more  
    tokens  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值