0%

2024-03-21-getopt_long

getopt_long

1
int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);  
  • argc和argv是main方法的入参,argc是长度,argv是地址数组指针

  • optstring是短选项字符串格式

    • 形式 a:bc::, b表示只有一个字符,没有参数;a:表示a后面可以加一个参数;c::表示参数可选,但是如果带参数不能有空格 -c100
    • eg:-a 200 b -c100
  • longopts是长选项结构体

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    struct option 
    {
    const char *name;
    int has_arg;
    int *flag;
    int val;
    };
    eg:
    static struct option longOpts[] = {
    { "daemon", no_argument, NULL, 'D' },
    { "dir", required_argument, NULL, 'd' },
    { "out", required_argument, NULL, 'o' },
    { "log", required_argument, NULL, 'l' },
    { "split", required_argument, NULL, 's' },
    { "http-proxy", required_argument, &lopt, 1 },
    { "http-user", required_argument, &lopt, 2 },
    { "http-passwd", required_argument, &lopt, 3 },
    { "http-proxy-user", required_argument, &lopt, 4 },
    { "http-proxy-passwd", required_argument, &lopt, 5 },
    { "http-auth-scheme", required_argument, &lopt, 6 },
    { "version", no_argument, NULL, 'v' },
    { "help", no_argument, NULL, 'h' },
    { 0, 0, 0, 0 }
  • name 是长选项

  • val是短选项

  • has_arg 是有没有参数

    • no_argument 无参数,
    • required_argument 有参数,且格式为 –o 100 或者–out=100
    • optional_argument有参数,格式只能为–out=100
  • flag参数有两个意思

    • 如果是NULL,命中长选项时返回短短选项字符串
    • 如果不为NULL,命中长选项时返回0,flag=短选项值
  • longindex longopts数组中匹配到的option位置

  • 全局变量

    • optarg:表示当前选项对应的参数值。
    • optind:表示的是下一个将被处理到的参数在argv中的下标值。
    • opterr:如果opterr = 0,在getopt、getopt_long、getopt_long_only遇到错误将不会输出错误信息到标准输出流。opterr在非0时,向屏幕输出错误。
    • optopt:表示没有被未标识的选项。
  • 返回值

    • 如果短选项找到,那么将返回短选项对应的字符。
    • 如果长选项找到,如果flag为NULL,返回val。如果flag不为空,返回0
    • 如果遇到一个选项没有在短字符、长字符里面。或者在长字符里面存在二义性的,返回“?”
    • 如果解析完所有字符没有找到(一般是输入命令参数格式错误,eg: 连斜杠都没有加的选项),返回“-1”
    • 如果选项需要参数,忘了添加参数。返回值取决于optstring,如果其第一个字符是“:”,则返回“:”,否则返回“?”。

      DEMO

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      111
      112
      113
      114
      115
      116
      117
      118
      119
      120
      121
      122
      123
      124
      125
      126
      127
      128
      129
      130
      131
      132
      133
      134
      135
      //
      // Created by juneleo on 2022/12/29.
      //



      #include<stdio.h>
      #include <getopt.h>
      #include<iostream>
      #include<string>
      #include<stdlib.h>
      using namespace std;

      void showUsage() {
      //cout << "Usage: " << PACKAGE_NAME << " [options] URL ..." << endl;
      cout << "Options:" << endl;
      cout << " -d, --dir=DIR The directory to store downloaded file." << endl;
      cout << " -o, --out=FILE The file name for downloaded file." << endl;
      cout << " -l, --log=LOG The file path to store log. If '-' is specified," << endl;
      cout << " log is written to stdout." << endl;
      cout << " -D, --daemon Run as daemon." << endl;
      cout << " -s, --split=N Download a file using s connections. s must be" << endl;
      cout << " between 1 and 5. If this option is specified the" << endl;
      cout << " first URL is used, and the other URLs are ignored." << endl;
      cout << " --http-proxy=HOST:PORT Use HTTP proxy server. This affects to all" << endl;
      cout << " URLs." << endl;
      cout << " --http-user=USER Set HTTP user. This affects to all URLs." << endl;
      cout << " --http-passwd=PASSWD Set HTTP password. This affects to all URLs." << endl;
      cout << " --http-proxy-user=USER Set HTTP proxy user. This affects to all URLs" << endl;
      cout << " --http-proxy-passwd=PASSWD Set HTTP proxy password. This affects to all URLs." << endl;
      cout << " --http-auth-scheme=SCHEME Set HTTP authentication scheme. Currently, BASIC" << endl;
      cout << " is the only supported scheme." << endl;
      cout << " -v, --version Print the version number and exit." << endl;
      cout << " -h, --help Print this message and exit." << endl;
      cout << "URL:" << endl;
      cout << " You can specify multiple URLs. All URLs must point to the same file" << endl;
      cout << " or a download fails." << endl;
      cout << "Examples:" << endl;
      cout << " Download a file by 1 connection:" << endl;
      cout << " aria2c http://AAA.BBB.CCC/file.zip" << endl;
      cout << " Download a file by 2 connections:" << endl;
      cout << " aria2c -s 2 http://AAA.BBB.CCC/file.zip" << endl;
      cout << " Download a file by 2 connections, each connects to a different server." << endl;
      cout << " aria2c http://AAA.BBB.CCC/file.zip http://DDD.EEE.FFF/GGG/file.zip" << endl;
      cout << "Reports bugs to <tujikawa at rednoah dot com>" << endl;
      }

      int main(int argc, char* argv[]) {
      bool stdoutLog = false;
      string logfile;
      string dir;
      string ufilename;
      int split = 0;
      bool daemonMode = false;
      int c;


      while(1) {
      int optIndex = 0;
      int lopt;
      static struct option longOpts[] = {
      { "daemon", no_argument, NULL, 'D' },
      { "dir", required_argument, NULL, 'd' },
      { "out", required_argument, NULL, 'o' },
      { "log", required_argument, NULL, 'l' },
      { "split", required_argument, NULL, 's' },
      { "http-proxy", required_argument, &lopt, 1 },
      { "http-user", required_argument, &lopt, 2 },
      { "http-passwd", required_argument, &lopt, 3 },
      { "http-proxy-user", required_argument, &lopt, 4 },
      { "http-proxy-passwd", required_argument, &lopt, 5 },
      { "http-auth-scheme", required_argument, &lopt, 6 },
      { "version", no_argument, NULL, 'v' },
      { "help", no_argument, NULL, 'h' },
      { 0, 0, 0, 0 }
      };
      c = getopt_long(argc, argv, "Dd:o:l:s:vh", longOpts, &optIndex);
      printf("返回值: %c\n",c);
      if(c == -1) {
      break;
      }
      switch(c) {
      case 0:{
      switch(lopt) {
      case 1: {
      printf("1: %s\n",optarg);
      break;
      }
      case 2:
      printf("2: %s\n",optarg);
      break;
      case 3:
      printf("3: %s\n",optarg);
      break;
      case 4:
      printf("4: %s\n",optarg);
      break;
      case 5:
      printf("5: %s\n",optarg);
      break;
      case 6:
      printf("6: %s\n",optarg);
      break;
      }
      break;
      }
      case 'D':
      printf("D: %s\n",optarg);
      break;
      case 'd':
      printf("d: %s\n",optarg);
      break;
      case 'o':
      printf("o: %s\n",optarg);
      break;
      case 'l':
      printf("l: %s\n",optarg);
      break;
      case 's':
      printf("s: %s\n",optarg);
      break;
      case 'v':
      printf("s: %s\n",optarg);
      //showVersion();
      exit(0);
      case 'h':
      showUsage();
      exit(0);
      default:
      showUsage();
      exit(1);
      }
      }
      return 0;
      }

      测试

      1
      2
      3
      4
      5
      6
      7
      ./getopt_test --out=file.txt --dir=/Users/juneleo/ --http-proxy=192.168.0.0       
      返回值: o
      o: file.txt
      返回值: d
      d: /Users/juneleo/
      返回值:
      1: 192.168.0.0