# Linux命令行解析函数getopt\_long()

Linux环境下大多数程序被编译成带参数运行的可执行程序，C语言提供了几个命令行参数解析函数来辅助完成工作。

### getopt\_long()

getopt()只能处理短选项，而getopt\_long()由于长选项结构体`option`返回的原因可以同时处理长选项和短选项。

```
#include <unistd.h>
extern char *optarg;
extern int optind, opterr, optopt;
​
#include <getopt.h>
int getopt(int argc, char * const argv[],const char *optstring);
int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);
int getopt_long_only(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);
```

* `argc`：参数个数
* `argv`：参数内容
* `optstring`：表示短选项字符串。

  形式如`a:b::cd:`，分别表示程序支持的命令行短选项有-a、-b、-c、-d，冒号含义如下：

  * 只有一个字符，不带冒号——只表示选项， 如：`-c`
  * 一个字符，后接一个冒号——表示选项后面带一个参数，如：`-a 100`
  * 一个字符，后接两个冒号——表示选项后面带一个可选参数，即参数可有可无， 如果带参数，则选项与参数直接不能有空格，如：`-b10`
* `longopts`：长选项结构体

  ```
  struct option 
  {  
       const char *name;  
       int         has_arg;  
       int        *flag;  
       int         val;  
  };
  ```

  (1)`name`：表示选项的名称,比如daemon,dir,out等

  (2)`has_arg`：表示选项后面是否携带参数，该参数有三个不同值，如下：

  * no\_argument(或者是0)时 ——参数后面不跟参数值
  * required\_argument(或者是1)时 ——参数输入格式为：--参数 值 或者 --参数=值
  * optional\_argument(或者是2)时 ——参数输入格式只能为：--参数=值

  (3)`flag`：

  * 如果参数为空NULL，那么当选中某个长选项的时候，getopt\_long将返回val值（这种情况下val通常被定义为短选项值）
  * 如果参数不为空，那么当选中某个长选项的时候，getopt\_long将返回0，并且将flag指针参数指向val值。

  (4)`val`：表示指定函数找到该选项时的返回值，或者当flag非空时指定flag指向的数据的值val
* `longindex`：当找到对应选项时返回的是该选项在longopts结构体数组中的下标
* 全局变量：
  * `optarg`：当前选项对应的参数值
  * `optind`：下一个将被处理到的参数在argv中的下标值
  * `opterr`：getopt()，getopt\_long()函数错误信息
  * `optopt`：最后一个未知选项
* 返回值：
  * 短选项找到，返回短选项对应的字符
  * 长选项找到，flag为NULL则返回val，flag不为NULL则返回0
  * 未找到返回-1

```
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
int main()
{
    while(1) {
        int c;
        struct option long_opts[] {
            {"input_img", required_argument, NULL, 'i'},
            {"input_fmt", required_argument, NULL, 's'},
            {"output_img", required_argument, NULL, 'o'},
            {"output_fmt", required_argument, NULL, 'f'},
            {"width", required_argument, NULL, 'w'},
            {"height", required_argument, NULL, 'd'},
            {"test", required_argument, &lopt, 1},
            {"help", no_argument, NULL, 'h'},
            {NULL , 0, NULL, 0}     // option结构体数组结束标志，不可省略
        };
        c = getopt_long(argc, argv, "i:s:o:f:w:d:h", long_opts, &option_index);
​
        if (c == -1) break;
​
        switch (c)
        {
        case 'i':
            image.path = optarg;
            break;
        case 's':
            image.src_fmt = (pix_fmt)atoi(optarg);
            break;
        case 'o':
            output_path = optarg;
            break;
        case 'f':
            image.dst_fmt = (pix_fmt)atoi(optarg);
            break;
        case 'w':
            image.width = atoi(optarg);
            break;
        case 'd':
            image.height = atoi(optarg);
            break;
        case 'h':
        default:
            // usage();
            exit(-1);
        }
    }
    return 0;
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ricardolu.gitbook.io/trantor/linux-ming-ling-hang-jie-xi-han-shu-getoptlong.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
