关于c++:Linux命令行参数解析getoptlong

  • 在linux中,所有皆文件,所有的可执行程序都能够通过命令行启动,程序启动时通常都会带上各种参数以控制程序的行为。所以解析命令行参数通常是一个可执行程序的第一步,上面就来介绍下常常用到的命令行参数的解析函数——getopt_long。
  • 咱们先来理解一下命令行参数。命令行参数能够分为两类,一类是短选项,一类是长选项。在命令行中”-“示意短选项,”–“则示意长选项。例如,在linux中最罕用的ls命令中“-a,-A,-b”都是短选项,而它们对应的长选项则是“–all,–almost-all, –escape”。它们还都可选择性的增加额定参数,比方“–block-size=SIZE”。
  • getopt_long反对解决长短选项的命令行解析,函数在<getopt.h>头文件中。其函数定义是:

    int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex); 
  • 接下来介绍一下其参数以及返回值。

    • argc和argv和main函数的两个参数统一。
    • optstring: 示意短选项字符串。
      模式如“a“,别离示意程序反对的命令行短选项有-a、-b、-c、-d,冒号含意如下:

        1. 只有一个字符,不带冒号——只示意选项, 如-c。
        2. 一个字符,后接一个冒号——示意选项前面带一个参数,如-a 100。
        3. 一个字符,后接两个冒号——示意选项前面带一个可选参数,即参数可有可无, 如果带参数,则选项与参数之间不能有空格,如-b123。

    • longopts:示意长选项构造体。其构造以及解释如下:

      struct option { 
      const char *name;// 示意的是长选项名称 
      int has_arg;// 示意选项前面是否携带参数。有3个值。
      // no_argument(或者是0),参数前面不跟参数值。
      // required_argument(或者是1),参数输出格局为:--参数 值 或者 --参数=值。
      // optional_argument(或者是2),参数输出格局只能为:--参数=值。
      int *flag;//用来决定函数的返回值。如果flag是null,则函数会返回与该项option匹配的val值,如果flag不是null,则函数返回0,并将flag指针参数指向与该项option匹配的val值。
      int val; //和flag联结决定返回值 
      } 
      • longindex:longindex不是null的话则指向的变量将记录longopts的下标值。
    • 返回值:

      1. 如果短选项找到,那么将返回短选项对应的字符。
      2. 如果长选项找到,且flag为null,返回val,flag不为null,返回0。
      3. 如果产生谬误,如:未辨认选项或者必须加参数的选项失落参数,返回“?”,如果在optstring中设置了第一个字符为“:”,失落参数返回“:”。
      4. 当缩写长选项引起歧义时或者不须要的选项强加了参数,都会返回“?”。
      5. 返回-1示意选项解决全副完结。
      6. 如果在输出的argv[]中蕴含了独立的“–”字符串,解析到这里返回-1,进行选项的解析。
  • 还有一些须要理解的全局变量:

    • optarg(指针):示意以后选项对应的参数值。
    • optind:示意的是下一个将被解决到的参数在argv中的下标值。
    • opterr:如果opterr = 0,遇到谬误将不会输入错误信息到规范输入流。opterr在非0时,向屏幕输入谬误。
    • optopt:示意出错或者未辨认的选项。
  • 注意事项:

    • longopts的最初一个元素必须是全0填充,否则会报段谬误
    • 短选项中每个选项都是惟一的。而长选项如果简写,也须要放弃唯一性。
  • 上面是一个简略的例子:

    /* 程序运行参数构造体 */
    struct InputArgs
    {
      std::string user_id;
      std::string user_name;
      std::string pwd;
    
      void printArgs();
    
      bool checkArgs()
      {
        if (user_id.empty())
        {
          return false;
        }
    
        if (user_name.empty())
        {
          return false;
        }
    
        if (pwd.empty())
        {
          return false;
        }
    
        return true;
      }
    };
    
    InputArgs g_input_arg_info;
    
    void InputArgs::printArgs(){
        printf("ARGS:  --= %s\n", userId.c_str());
        printf("        --userName = %s\n", user_name.c_str());
        printf("        --pwd = %s\n", pwd.c_str());
    }
    
    /* 参数解析 */
    const char* short_options = "i:n:p:";
    struct option long_options[] = {
        { "userId", required_argument, NULL, 'i' },
        { "userName", required_argument, NULL, 'n' },
        { "pwd", required_argument, NULL, 'p' },
        { 0, 0, 0, 0 }, 
    };
    
    void print_usage(){
        printf("DESCRIPTION\n");
        printf("  --userId, -i\n");
        printf("  --userName, -n\n");
        printf("  --pwd, -p\n");
    }
    
    void print_arg(int argc, char *argv[])
    {
      for (int i = 0; i < argc; i++)
      {
        printf("%s\n", argv[i]);
      }
    }
    
    int parse_arg(int argc, char *argv[])
    {
      print_arg(argc, argv);
      int c;
      std::string opt;
      while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) !=
             -1)
      {
        switch (c)
        {
        case 'i':
          opt = optarg;
          g_input_arg_info.user_id = opt;
          break;
        case 'n':
          opt = optarg;
          g_input_arg_info.user_name = opt;
          break;
        case 'p':
          opt = optarg;
          g_input_arg_info.pwd = opt;
          break;
        default:
          return -1;
        }
      }
    
      if (false == g_input_arg_info.checkArgs())
      {
        return -2;
      }
    
      return 0;
    }
    
    int main(int argc, char *argv[])
    {
      if (0 != parse_arg(argc, argv))
      {
        print_usage();
        printf("parse input args failed!\n");
        return 1;
      }
    
      g_input_arg_info.printArgs();
    
      // do things here
    }

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理