美文网首页C/C艹
命令行参数解析(c编程)

命令行参数解析(c编程)

作者: 御浅永夜 | 来源:发表于2018-06-16 12:46 被阅读0次

    该文主要介绍c语言通过命令行方式输入参数,程序如何获取并解析参数。
    例如:./a.out -a red -b blue
    当你输入上面的命令,你想将red值赋给a,blue值赋给b。当然你可以通过解析argv数组来获取(getopt系列肯定也是这么干的)。

    1. 接口介绍

    1.1 getopt

    1.1.1 函数原型

           #include <unistd.h>
    
           int getopt(int argc, char * const argv[],
                      const char *optstring);
    
           extern char *optarg;
           extern int optind, opterr, optopt;
    

    1.1.2 简介

    getopt()函数用于解析命令行参数,以-开头的argv元素是选项元素,重复调用getopt()函数将返回每个选项元素的选项字符。
    eg.当你输入./a.out -a red -b blue,将得到

    argc=5
    argv={
      "0" => "./a.out"
      "1" => "-a"
      "2" => "red"
      "3" => "-b"
      "4" => "blue"
    }
    

    -a-b就是选项参数,第一次调用getopt将返回a,第二次调用将返回b

    当getopt()找到一个选项字符之后,它首先返回该字符,更新外部变量optind和一个静态变量nextchar。当遍历所有的选项字符,没有多余的选项之后,getopt()函数返回-1

    变量optind是argv中要处理的下一个元素索引。重复调用之后,该值累加。可将该值重置,重新获取参数选项。

    optstring是一个包含合法选项字符的字符串。若字符后跟一个冒号,则该选项需要一个参数,getopt()设置一个指针指向同一个argv元素的下一个文本中;两个冒号表示该选项需要一个可选的参数。

    1.1.3 示例

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    
    int main(int argc, char *argv[])
    {
      /*
       * 打印参数列表
       */
      printf("argc=%d\n",argc);
      for(int i=0;i<argc;i++) {
        printf("argv[%d]=%s ",i, argv[i]);
      }
      printf("\n");                                             
      int opt,flags;
      char *avalue,*bvalue;
    
      flags = 0;
      char *optstring = "a:b:c"; 
      while ((opt = getopt(argc, argv, optstring)) != -1) {
        switch(opt) {
          case 'a': 
            flags = 1;
            avalue = optarg;
            break;
          case 'b': 
            flags = 2;
            bvalue = optarg;
            break;
          case 'c': 
            flags = 3;
            break;
          default:
            flags = 5;
        }
      }
      printf("flags=%d; optind=%d; avalue=%s; bvalue=%s\n", flags, optind, avalue,bvalue);
    
      exit(EXIT_SUCCESS);
    }
    

    编译运行:

    ~ gcc getopt.c -o getopt -Wall
    ~ ./getopt -b d -a a
    argc=5
    argv[0]=./getopt argv[1]=-b argv[2]=d argv[3]=-a argv[4]=a 
    flags=1; optind=5; avalue=a; bvalue=d
    

    1.2 getopt_long()

    允许长参数名

    1.2.1 函数原型

           #include <getopt.h>
    
           int getopt_long(int argc, char * const argv[],
                      const char *optstring,
                      const struct option *longopts, int *longindex);
    

    1.2.2 简介

    getopt_long()函数相对于getopt(),增加了长参数列表。

    longopts指向一个由option结构体组成的数组。option结构体定义在<getopt.h>中:

    struct option {
      const char *name;    //参数完整名称
      int         has_arg;      //该参数是否带有参数值
      int        *flag;             //一般设置为NULL
      int         val;
    };
    
    • name:长参数名称
    • has_arg:设定这个长参数是否带参数值
      • no_argument/0:不需要参数值
      • required_argument/1:需要一个参数值
      • optional_argument/2:表明其后面是否带参数值都可以
    • flag:设定一个长参数如何返回
      • NULL:getopt_long()返回val。
      • 非空:val的值会被赋到flag指向的整型数中,而函数返回值为0
    • val:函数找到该选项时的返回值,或当flag非空时指定flag指向的数据的值

    该数组最后一个参数需要设置为0。

    如果longindex不为NULL,则它指向一个变量,该变量设置为long选项相对于longopts的索引。

    1.2.3 实例

    #include <stdio.h>     /* for printf */ #include <stdlib.h>    /* for exit */ #include <getopt.h>
    
    int main(int argc, char **argv) {
      int c;
      int digit_optind = 0;
    
      while (1) {
        int this_option_optind = optind ? optind : 1;
        int option_index = 0;
        static struct option long_options[] = {
            {"add",     required_argument, 0,  0 },
            {"append",  no_argument,       0,  0 },
            {"delete",  required_argument, 0,  0 },
            {"verbose", no_argument,       0,  0 },
            {"create",  required_argument, 0, 'c'},
            {"file",    required_argument, 0,  0 },
            {0,         0,                 0,  0 }
        };
    
        c = getopt_long(argc, argv, "abc:d:012",
                 long_options, &option_index);
        if (c == -1)
            break;
    
        switch (c) {
        case 0:
            printf("option %s", long_options[option_index].name);
            if (optarg)
                printf(" with arg %s", optarg);
            printf("\n");
            break;
    
        case '0':
        case '1':
        case '2':
            if (digit_optind != 0 && digit_optind != this_option_optind)
              printf("digits occur in two different argv-elements.\n");
            digit_optind = this_option_optind;
            printf("option %c\n", c);
            break;
    
        case 'a':
            printf("option a\n");
            break;
    
        case 'b':
            printf("option b\n");
            break;
    
        case 'c':
            printf("option c with value '%s'\n", optarg);
            break;
    
        case 'd':
            printf("option d with value '%s'\n", optarg);
            break;
    
        case '?':
            break;
    
        default:
            printf("?? getopt returned character code 0%o ??\n", c);
        }
      }
    
      if (optind < argc) {
          printf("non-option ARGV-elements: ");
          while (optind < argc)
              printf("%s ", argv[optind++]);
          printf("\n");
      }
    
      exit(EXIT_SUCCESS);
    }
    

    2. 使用总结

    谁也没法天生就知道如何优雅的使用,从笨拙到放弃才是常态:),我这里总结了模板,仅供参考,与openssl里将getopt里将其封装相比,思想上差的不是一星半点。

    2.1 蹒跚学步

    /*
     * 命令行参数列表
     */
    static struct option long_options[] = {
      {"mode",1,0,'m'},
      {"algorithom",1,0,'a'},
      {"key_HEX",0,0,'k'},
      {"iv_HEX",0,0,'v'},
      {"input",0,0,'i'},
      {"output",0,0,'o'},
      {"format",1,0,'f'},
      {"help",0,0,'h'}
    };
    while( (c = getopt_long(argc,argv,"m:a:k:v:i:o:f:h",long_options,&option_index)) != -1){
      switch(c){
        case 'm':
          //optarg此时指向参数值
          break;
      }
    }
    

    相关文章

      网友评论

        本文标题:命令行参数解析(c编程)

        本文链接:https://www.haomeiwen.com/subject/irbosftx.html