Cのプログラムでコマンドラインからパラメータを受けたい訳ですが、自力でやろうとしてもargv経由で文字列配列が渡されるだけなので非常に面倒です(LL病な自分としてはハッシュで欲しい)。例えば以下のgrepコマンドの用に複数のパラメータを順不同で受けたいとかになると、かなり大変ですね。
$ grep -nH -I -R search_text *
そこで、なんか無いのかと思って調べてみるとgetoptを使えば良い事がわかりました。
この関数を使うとパラメータを受ける処理を以下のように書けます。第3引数で取り得るオプションの種類を指定します。”abcd:e:”の場合は、取り得るオプションはa,b,c,d,eの5種類で、その内コロン付きのdとeは値を取ります。
#include "stdio.h" #include "stdlib.h" #include "getopt.h" int main(int argc, char** argv) { int result = 0; while ((result = getopt(argc, argv, "abcd:e:")) != -1) { switch (result) { case 'a': case 'b': case 'c': printf("option: %c applied\n", result); break; case 'd': case 'e': printf("option %c applied with %s\n", result, optarg); break; case ':': // no value applied case '?': // invalid option exit(1); } } printf("@@ param start @@\n"); for(int i = optind; i < argc; i++) { printf("param: %s \n", argv[i]); } }
このプログラムは、例えば以下のように実行できます。オプションの指定は順不同に書けますし、-bcの用にまとめて指定する事もできます。素晴しいですね。
$ ./option_test -a -bc -d val_for_d param1 param2 option: a applied option: b applied option: c applied option d applied with val_for_d @@ param start @@ param: param1 param: param2
さてgetoptで殆どの要求には対応できますが、所謂longオプションには対応していません。しかし俺々コマンドでもカッコ良く--verboseとか--helpとかやりたい!という熱い思いをかなえる為(かどうかは知りませんが)にgetopt_longという関数が準備されています。
結論のコードが以下になります。殆どgetoptと同じように使えますが、longオプション用の配列(long_opts)を準備する必要があり、少し面倒ですね。覚える必要があるのは、option構造体のvalメンバ(コード中の4つ目の値)がgetopt_long関数の戻り値になる事です。この値を弄ることでshortオプションのエイリアスとして使う事が出来ますね。
#include "stdio.h" #include "stdlib.h" #include "getopt.h" int main(int argc, char** argv) { struct option long_opts[] = { {"ls", 0, NULL, 0}, // ls doesn't have option value {"type", 1, NULL, 1}, // type has option value {"help", 0, NULL, 'h'}, // alias of h {"version", 0, NULL, 'v'}, // alias of v {0, 0, 0, 0} // 最後の要素は全部0の必要があります。 }; int result = 0; int opt_idx = 0; while ((result = getopt_long(argc, argv, "hv", long_opts, &opt_idx)) != -1) { switch (result) { // for long options case 0: // ls case 1: // type printf("[%s] applied: %s\n", long_opts[opt_idx].name, optarg); break; // for short options case 'h': printf("help! \n"); break; case 'v': printf("version! \n"); break; case ':': case '?': exit(1); } } printf("@@ param start @@\n"); for(int i = optind; i < argc; i++) { printf("param: %s \n", argv[i]); } }
例えば以下のように実行できます。
$ ./option_test -v --type=text --ls . hello.txt version! [type] applied: text [ls] applied: (null) @@ param start @@ param: . param: hello.txt
遅まきながらCでコマンドライン引数を割と自由に扱えるようになりました。個人的には、rmコマンドのソースが分かり易くてオススメかなぁと思います。
関連する記事
タグ: getopt, getopt_long


[...] This post was mentioned on Twitter by taichino. taichino said: Blogged Cでのコマンドラインパラメータの受け方メモ http://bit.ly/cfQWD5 [...]