コマンドライン引数で自作のオプションを指定する

プログラム実行時に自作のオプションで動作を変更したい時があると思います。
そういうときに便利なgetopt_long()を使用してみたので、備忘録的にメモしておきます。

とりあえずサンプルコード

#include <stdio.h>
#include <getopt.h>

int main(int argc, char **argv)
{
  int opt1 = 0;
  int opt2 = 0;
  int opt3 = 0;
  struct option longopts[] = {
    {"option1", required_argument, NULL, 1},
    {"option2", required_argument, NULL, 2},
    {"option3", no_argument, NULL, 3},
    {0, 0, 0, 0},
  };
  int opt;
  int longindex;
  
  while((opt = getopt_long(argc, argv, "option1:option2:otption3", longopts, &longindex)) != -1) {
    switch (opt) {
    case 1:
      opt1 = atoi(optarg);
      printf("opt1 = %d\n", opt1);
      break;
    case 2:
      opt2 = atoi(optarg);
      printf("opt2 = %d\n", opt2);
      break;
    case 3:
      opt3 = 3;
      printf("opt3 = %d\n", opt3);
      break;
    default:
      printf("?? getopt_long returned character 0%o ??\n", opt);
    }
  }

  return 0;
}

コンパイルして実行すると以下のような感じです。

$ ./a.out --option1=1 --option2=2 --option3
opt1 = 1
opt2 = 2
opt3 = 3

オプションは全部指定しなくても大丈夫です

$ ./a.out --option1=1 --option3
opt1 = 1
opt3 = 3

今わかっているレベルでの説明を以下に記載します。
(間違っている可能性あります。)

  struct option longopts[] = {
    {"option1", required_argument, NULL, 1},
    {"option2", required_argument, NULL, 2},
    {"option3", no_argument, NULL, 3},
    {0, 0, 0, 0},
  };

option構造体は以下のような定義になっています。

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

"name"には使用したいオプション名を設定します。
"has_arg"は引数の設定をするようです。
引数をつけたい(--option1=1とかやりたい)時は"required_argument"、別に引数いらないときは時は"no_argument"と指定します。どっちでもよくする場合は、"optional_argument"と指定します。
"flag"はよく理解できていませんが、"NULL"指定するとgetopt_longが成功した時の戻りとして"val"の値を返すような設定になります。
つまり、今回の場合、"--option1=1"みたいな指定があるとgetopt_longは戻り値として"1"を返すようになるようです。
"val"は前記のように、getopt_long()の戻り値を設定します。

getopt_longの引数は5つです。
"argc"と"argv"はmain関数の引数をそのままわたしています。
"option1:option2:otption3"はオプション文字列するようです。
":"があると引数があるオプションで、ないと引数がないオプションとなるようです。
("::"だと、引数があってもなくてもよい設定になるようです。)
でもoption構造体でも同様の設定しているでの、ここで設定する意味がわかりませんでした。
(仮に""だけでも動作しましたし、別の適当な文字列でも動作しているようでした。。。。)

"longopts"はoption構造体を指定して、"longindex"指定されたオプションが定義してあるオプション構造体のインデックスを指しています。

while文以下はオプションによって処理を分けているだけなので説明は省略します。


以下は参考にさせてもらったサイトです。
getopt_long関数の利用 - コマンドラインオプションの処理 - 碧色工房
C言語でコマンドライン引数を取り扱う方法
getopt_long(3) — manpages-ja-dev — Debian testing — Debian Manpages
getoptを使う - Qiita