Cでのコマンドラインパラメータの受け方メモ 

はてなブックマーク - Cでのコマンドラインパラメータの受け方メモ
Bookmark this on Delicious

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コマンドのソースが分かり易くてオススメかなぁと思います。

関連する記事

  • 関連する記事はありません

タグ: ,

コメント / トラックバック1件

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

コメントをどうぞ